]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
proxy_auth and ident ACL types converted to use splay trees
authorhno <>
Sun, 7 Jan 2001 21:47:17 +0000 (21:47 +0000)
committerhno <>
Sun, 7 Jan 2001 21:47:17 +0000 (21:47 +0000)
this should make large user lists much more efficient.

by Francesco Chemolli

src/acl.cc
src/enums.h
src/mem.cc
src/structs.h
src/typedefs.h

index 2a5592decf65653b1b43ee45b5dca35419993358..a3b167de1829c8e13ee3f05e74fd19d606239397 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: acl.cc,v 1.231 2001/01/05 09:51:36 adrian Exp $
+ * $Id: acl.cc,v 1.232 2001/01/07 14:47:17 hno Exp $
  *
  * DEBUG: section 28    Access Control
  * AUTHOR: Duane Wessels
@@ -41,6 +41,7 @@ static FILE *aclFile;
 static hash_table *proxy_auth_cache = NULL;
 
 static void aclParseDomainList(void *curlist);
+static void aclParseProxyAuthList(void **current);
 static void aclParseIpList(void *curlist);
 static void aclParseIntlist(void *curlist);
 static void aclParseWordList(void *curlist);
@@ -57,7 +58,7 @@ static struct _acl *aclFindByName(const char *name);
 static int aclMatchAcl(struct _acl *, aclCheck_t *);
 static int aclMatchIntegerRange(intrange * data, int i);
 static int aclMatchTime(acl_time_data * data, time_t when);
-static int aclMatchUser(wordlist * data, const char *ident);
+static int aclMatchUser(void *proxyauth_acl, char *user);
 static int aclMatchIp(void *dataptr, struct in_addr c);
 static int aclMatchDomainList(void *dataptr, const char *);
 static int aclMatchIntegerRange(intrange * data, int i);
@@ -634,6 +635,48 @@ aclParseWordList(void *curlist)
        wordlistAdd(curlist, t);
 }
 
+static void
+aclParseProxyAuthList(void **current)
+{
+    char *t = NULL;
+    acl_proxy_auth_data *data;
+    splayNode *Top = NULL;
+
+    debug(28, 2) ("aclParseProxyAuthList: parsing authlist\n");
+    if (*current == NULL) {
+       debug(28, 3) ("aclParseProxyAuthList: current is null. Creating\n");
+       *current = memAllocate(MEM_ACL_PROXY_AUTH_DATA);        /*we rely on mA. zeroing */
+    }
+    data = *current;
+    if ((t = strtokFile())) {
+       debug(28, 5) ("aclParseProxyAuthList: First token is %s\n", t);
+       if (strcmp("-i", t) == 0) {
+           debug(28, 5) ("aclParseProxyAuthList: Going case-insensitive\n");
+           data->flags.case_insensitive = 1;
+       } else if (strcmp("REQUIRED", t) == 0) {
+           debug(28, 5) ("aclParseProxyAuthList: REQUIRED-type enabled\n");
+           data->flags.required = 1;
+       } else {
+           if (data->flags.case_insensitive)
+               Tolower(t);
+           Top = splay_insert(xstrdup(t), Top, (SPLAYCMP *) strcmp);
+       }
+    }
+    debug(28, 3) ("aclParseProxyAuthList: Case-insensitive-switch is %d\n",
+       data->flags.case_insensitive);
+    /* we might inherit from a previous declaration */
+
+    debug(28, 4) ("aclParseProxyAuthList: parsing proxy-auth list\n");
+    while ((t = strtokFile())) {
+       debug(28, 6) ("aclParseProxyAuthList: Got token: %s\n", t);
+       if (data->flags.case_insensitive)
+           Tolower(t);
+       Top = splay_insert(xstrdup(t), Top, (SPLAYCMP *) strcmp);
+    }
+    data->names = Top;
+}
+
+
 /**********************/
 /* aclParseDomainList */
 /**********************/
@@ -745,7 +788,7 @@ aclParseAclLine(acl ** head)
        aclParseMethodList(&A->data);
        break;
     case ACL_PROXY_AUTH:
-       aclParseWordList(&A->data);
+       aclParseProxyAuthList(&A->data);
        if (!proxy_auth_cache) {
            /* First time around, 7921 should be big enough */
            proxy_auth_cache = hash_create((HASHCMP *) strcmp, 7921, hash_string);
@@ -1009,20 +1052,33 @@ aclMatchRegex(relist * data, const char *word)
 }
 
 static int
-aclMatchUser(wordlist * data, const char *user)
+aclMatchUser(void *proxyauth_acl, char *user)
 {
+    acl_proxy_auth_data *data = (acl_proxy_auth_data *) proxyauth_acl;
+    splayNode *Top = data->names;
+
+    debug(28, 7) ("aclMatchUser: user is %s, case_insensitive is %d\n",
+       user, data->flags.case_insensitive);
+    debug(28, 8) ("Top is %p, Top->data is %s\n", Top,
+       (Top != NULL ? (Top)->data : "Unavailable"));
+
     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;
+
+    if (data->flags.case_insensitive)
+       Tolower(user);
+
+    if (data->flags.required) {
+       debug(28, 7) ("aclMatchUser: user REQUIRED and auth-info present.\n");
+       return 1;
     }
-    return 0;
+    Top = splay_splay(user, Top, (SPLAYCMP *) strcmp);
+    /* Top=splay_splay(user,Top,(SPLAYCMP *)dumping_strcmp); */
+    debug(28, 7) ("aclMatchUser: returning %d,Top is %p, Top->data is %s\n",
+       !splayLastResult,
+       Top, (Top ? Top->data : "Unavailable"));
+    data->names = Top;
+    return !splayLastResult;
 }
 
 static int
@@ -1892,6 +1948,15 @@ aclFreeIpData(void *p)
     memFree(p, MEM_ACL_IP_DATA);
 }
 
+static void
+aclFreeProxyAuthData(void *data)
+{
+    acl_proxy_auth_data *d = data;
+    splay_destroy(d->names, xfree);
+    memFree(d, MEM_ACL_PROXY_AUTH_DATA);
+}
+
+
 void
 aclDestroyAcls(acl ** head)
 {
@@ -1913,12 +1978,16 @@ aclDestroyAcls(acl ** head)
            break;
 #if SQUID_SNMP
        case ACL_SNMP_COMMUNITY:
+           wordlistDestroy((wordlist **) & a->data);
+           break;
 #endif
 #if USE_IDENT
        case ACL_IDENT:
+           wordlistDestroy((wordlist **) & a->data);
+           break;
 #endif
        case ACL_PROXY_AUTH:
-           wordlistDestroy((wordlist **) & a->data);
+           aclFreeProxyAuthData(a->data);
            break;
        case ACL_TIME:
            aclDestroyTimeList(a->data);
@@ -2094,6 +2163,27 @@ aclIpNetworkCompare(const void *a, const void *b)
     return rc;
 }
 
+static void
+aclDumpProxyAuthListWalkee(void *node_data, void *outlist)
+{
+    /* outlist is really a wordlist ** */
+    wordlistAdd(outlist, node_data);
+}
+
+wordlist *
+aclDumpProxyAuthList(acl_proxy_auth_data * data)
+{
+    wordlist *wl = NULL;
+    if ((data->flags.case_insensitive) != 0)
+       wordlistAdd(&wl, "-i");
+    /* damn this is VERY inefficient for long ACL lists... filling
+     * a wordlist this way costs Sum(1,N) iterations. For instance
+     * a 1000-elements list will be filled in 499500 iterations.
+     */
+    splay_walk(data->names, aclDumpProxyAuthListWalkee, &wl);
+    return wl;
+}
+
 static void
 aclDumpIpListWalkee(void *node, void *state)
 {
@@ -2235,6 +2325,8 @@ aclDumpGeneric(const acl * a)
        break;
 #if SQUID_SNMP
     case ACL_SNMP_COMMUNITY:
+       return wordlistDup(a->data);
+       break;
 #endif
 #if USE_IDENT
     case ACL_IDENT:
@@ -2245,7 +2337,7 @@ aclDumpGeneric(const acl * a)
        break;
 #endif
     case ACL_PROXY_AUTH:
-       return wordlistDup(a->data);
+       return aclDumpProxyAuthList(a->data);
        break;
     case ACL_TIME:
        return aclDumpTimeSpecList(a->data);
index e4b63f0e913f1dec29025cf1775a5e87f0c80708..2f00c510c43340640df350d701f666ccf00f6e5a 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: enums.h,v 1.179 2001/01/06 11:45:46 hno Exp $
+ * $Id: enums.h,v 1.180 2001/01/07 14:47:17 hno Exp $
  *
  *
  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
@@ -517,6 +517,7 @@ typedef enum {
     MEM_ACL_IP_DATA,
     MEM_ACL_LIST,
     MEM_ACL_NAME_LIST,
+    MEM_ACL_PROXY_AUTH_DATA,
     MEM_ACL_PROXY_AUTH_USER,
     MEM_ACL_TIME_DATA,
     MEM_CACHEMGR_PASSWD,
index 022f00e3d960d50c5f4a6ff6850debf09f4ba9a7..14ee3eb9bf14ca92414c3e62cf3d6e82c628f797 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: mem.cc,v 1.49 2000/10/17 08:06:04 adrian Exp $
+ * $Id: mem.cc,v 1.50 2001/01/07 14:47:17 hno Exp $
  *
  * DEBUG: section 13    High Level Memory Pool Management
  * AUTHOR: Harvest Derived
@@ -204,6 +204,8 @@ memInit(void)
     memDataInit(MEM_ACL_LIST, "acl_list", sizeof(acl_list), 0);
     memDataInit(MEM_ACL_NAME_LIST, "acl_name_list", sizeof(acl_name_list), 0);
     memDataInit(MEM_ACL_TIME_DATA, "acl_time_data", sizeof(acl_time_data), 0);
+    memDataInit(MEM_ACL_PROXY_AUTH_DATA, "acl_proxy_auth_data",
+       sizeof(acl_proxy_auth_data), 0);
     memDataInit(MEM_ACL_PROXY_AUTH_USER, "acl_proxy_auth_user",
        sizeof(acl_proxy_auth_user), 0);
     memDataInit(MEM_CACHEMGR_PASSWD, "cachemgr_passwd",
index ed20849b14194db23dd2b3ccdd74da1e351cc24e..7d30c95d07ffe7a8ec844bf6effb0262d6b032c0 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: structs.h,v 1.372 2001/01/05 03:58:18 wessels Exp $
+ * $Id: structs.h,v 1.373 2001/01/07 14:47:17 hno Exp $
  *
  *
  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
@@ -31,6 +31,9 @@
  *
  */
 
+#include "config.h"
+#include "splay.h"
+
 struct _dlink_node {
     void *data;
     dlink_node *prev;
@@ -42,6 +45,15 @@ struct _dlink_list {
     dlink_node *tail;
 };
 
+struct _acl_proxy_auth_data {
+    splayNode *names;
+    struct {
+       unsigned int case_insensitive:1;
+       unsigned int required:1;
+    } flags;
+};
+
+
 struct _acl_ip_data {
     struct in_addr addr1;      /* if addr2 non-zero then its a range */
     struct in_addr addr2;
index 94f6a36c05e953a9af32ea4e847c6dee5c9bb8b9..ca4675c05c720ae0e8363e167577e3b0b9a05859 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: typedefs.h,v 1.113 2001/01/05 09:51:41 adrian Exp $
+ * $Id: typedefs.h,v 1.114 2001/01/07 14:47:17 hno Exp $
  *
  *
  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
@@ -62,6 +62,7 @@ typedef struct _acl_time_data acl_time_data;
 typedef struct _acl_name_list acl_name_list;
 typedef struct _acl_deny_info_list acl_deny_info_list;
 typedef struct _acl_proxy_auth acl_proxy_auth;
+typedef struct _acl_proxy_auth_data acl_proxy_auth_data;
 typedef struct _acl_proxy_auth_user acl_proxy_auth_user;
 typedef struct _acl_arp_data acl_arp_data;
 typedef struct _acl acl;