]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - src/external_acl.cc
Merge form trunk
[thirdparty/squid.git] / src / external_acl.cc
index 7948822189b75ad88674021bafe3937b26c657a1..fb090b7d5a917cf67b35c1a657b3b15dc2b42286 100644 (file)
  */
 
 #include "squid.h"
-#include "CacheManager.h"
+#include "mgr/Registration.h"
 #include "ExternalACL.h"
 #include "ExternalACLEntry.h"
 #include "auth/UserRequest.h"
 #include "SquidTime.h"
 #include "Store.h"
 #include "fde.h"
-#include "ACLChecklist.h"
-#include "ACL.h"
+#include "acl/FilledChecklist.h"
+#include "acl/Acl.h"
 #if USE_IDENT
-#include "ACLIdent.h"
+#include "ident/AclIdent.h"
 #endif
+#include "ip/tools.h"
 #include "client_side.h"
+#include "comm/Connection.h"
 #include "HttpRequest.h"
 #include "HttpReply.h"
-#include "authenticate.h"
+#include "auth/Acl.h"
+#include "auth/Gadgets.h"
 #include "helper.h"
 #include "MemBuf.h"
+#include "rfc1738.h"
 #include "URLScheme.h"
 #include "wordlist.h"
 
@@ -71,7 +75,7 @@
 
 typedef struct _external_acl_format external_acl_format;
 
-static char *makeExternalAclKey(ACLChecklist * ch, external_acl_data * acl_data);
+static char *makeExternalAclKey(ACLFilledChecklist * ch, external_acl_data * acl_data);
 static void external_acl_cache_delete(external_acl * def, external_acl_entry * entry);
 static int external_acl_entry_expired(external_acl * def, external_acl_entry * entry);
 static int external_acl_grace_expired(external_acl * def, external_acl_entry * entry);
@@ -105,9 +109,7 @@ public:
 
     wordlist *cmdline;
 
-    int children;
-
-    int concurrency;
+    HelperChildConfig children;
 
     helper *theHelper;
 
@@ -121,6 +123,12 @@ public:
 
     dlink_list queue;
 
+    /**
+     * Configuration flag. May only be altered by the configuration parser.
+     *
+     * Indicates that all uses of this external_acl_type helper require authentication
+     * details to be processed. If none are available its a fail match.
+     */
     bool require_auth;
 
     enum {
@@ -128,7 +136,7 @@ public:
         QUOTE_METHOD_URL
     } quote;
 
-    IpAddress local_addr;
+    Ip::Address local_addr;
 };
 
 struct _external_acl_format {
@@ -140,6 +148,10 @@ struct _external_acl_format {
 #endif
         EXT_ACL_SRC,
         EXT_ACL_SRCPORT,
+#if USE_SQUID_EUI
+        EXT_ACL_SRCEUI48,
+        EXT_ACL_SRCEUI64,
+#endif
         EXT_ACL_MYADDR,
         EXT_ACL_MYPORT,
         EXT_ACL_URI,
@@ -204,7 +216,7 @@ free_external_acl(void *data)
 
     if (p->theHelper) {
         helperShutdown(p->theHelper);
-        helperFree(p->theHelper);
+        delete p->theHelper;
         p->theHelper = NULL;
     }
 
@@ -289,11 +301,13 @@ parse_externalAclHelper(external_acl ** list)
     /* set defaults */
     a->ttl = DEFAULT_EXTERNAL_ACL_TTL;
     a->negative_ttl = -1;
-    a->children = DEFAULT_EXTERNAL_ACL_CHILDREN;
+    a->cache_size = 256*1024;
+    a->children.n_max = DEFAULT_EXTERNAL_ACL_CHILDREN;
+    a->children.n_startup = a->children.n_max;
+    a->children.n_idle = 1;
     a->local_addr.SetLocalhost();
     a->quote = external_acl::QUOTE_METHOD_URL;
 
-
     token = strtok(NULL, w_space);
 
     if (!token)
@@ -310,9 +324,16 @@ parse_externalAclHelper(external_acl ** list)
         } else if (strncmp(token, "negative_ttl=", 13) == 0) {
             a->negative_ttl = atoi(token + 13);
         } else if (strncmp(token, "children=", 9) == 0) {
-            a->children = atoi(token + 9);
+            a->children.n_max = atoi(token + 9);
+            debugs(0, 0, "WARNING: external_acl_type option children=N has been deprecated in favor of children-max=N and children-startup=N");
+        } else if (strncmp(token, "children-max=", 13) == 0) {
+            a->children.n_max = atoi(token + 13);
+        } else if (strncmp(token, "children-startup=", 17) == 0) {
+            a->children.n_startup = atoi(token + 17);
+        } else if (strncmp(token, "children-idle=", 14) == 0) {
+            a->children.n_idle = atoi(token + 14);
         } else if (strncmp(token, "concurrency=", 12) == 0) {
-            a->concurrency = atoi(token + 12);
+            a->children.concurrency = atoi(token + 12);
         } else if (strncmp(token, "cache=", 6) == 0) {
             a->cache_size = atoi(token + 6);
         } else if (strncmp(token, "grace=", 6) == 0) {
@@ -333,11 +354,9 @@ parse_externalAclHelper(external_acl ** list)
                 debugs(3, 0, "WARNING: Error converting " << a->local_addr << " to IPv4 in " << a->name );
             }
         } else if (strcmp(token, "ipv6") == 0) {
-#if !USE_IPV6
-            debugs(3, 0, "WARNING: --enable-ipv6 required for external ACL helpers to use IPv6: " << a->name );
-#else
-            (void)0;
-#endif
+            if (!Ip::EnableIpv6)
+                debugs(3, 0, "WARNING: --enable-ipv6 required for external ACL helpers to use IPv6: " << a->name );
+            // else nothing to do.
         } else {
             break;
         }
@@ -345,6 +364,16 @@ parse_externalAclHelper(external_acl ** list)
         token = strtok(NULL, w_space);
     }
 
+    /* check that child startup value is sane. */
+    if (a->children.n_startup > a->children.n_max)
+        a->children.n_startup = a->children.n_max;
+
+    /* check that child idle value is sane. */
+    if (a->children.n_idle > a->children.n_max)
+        a->children.n_idle = a->children.n_max;
+    if (a->children.n_idle < 1)
+        a->children.n_idle = 1;
+
     if (a->negative_ttl == -1)
         a->negative_ttl = a->ttl;
 
@@ -384,6 +413,12 @@ parse_externalAclHelper(external_acl ** list)
             format->type = _external_acl_format::EXT_ACL_SRC;
         else if (strcmp(token, "%SRCPORT") == 0)
             format->type = _external_acl_format::EXT_ACL_SRCPORT;
+#if USE_SQUID_EUI
+        else if (strcmp(token, "%SRCEUI48") == 0)
+            format->type = _external_acl_format::EXT_ACL_SRCEUI48;
+        else if (strcmp(token, "%SRCEUI64") == 0)
+            format->type = _external_acl_format::EXT_ACL_SRCEUI64;
+#endif
         else if (strcmp(token, "%MYADDR") == 0)
             format->type = _external_acl_format::EXT_ACL_MYADDR;
         else if (strcmp(token, "%MYPORT") == 0)
@@ -402,7 +437,6 @@ parse_externalAclHelper(external_acl ** list)
             format->type = _external_acl_format::EXT_ACL_METHOD;
 
 #if USE_SSL
-
         else if (strcmp(token, "%USER_CERT") == 0)
             format->type = _external_acl_format::EXT_ACL_USER_CERT_RAW;
         else if (strcmp(token, "%USER_CERTCHAIN") == 0)
@@ -414,11 +448,11 @@ parse_externalAclHelper(external_acl ** list)
             format->type = _external_acl_format::EXT_ACL_USER_CERT;
             format->header = xstrdup(token + 11);
         }
-
 #endif
         else if (strcmp(token, "%EXT_USER") == 0)
             format->type = _external_acl_format::EXT_ACL_EXT_USER;
         else {
+            debugs(0,0, "ERROR: Unknown Format token " << token);
             self_destruct();
         }
 
@@ -470,11 +504,17 @@ dump_externalAclHelper(StoreEntry * sentry, const char *name, const external_acl
         if (node->grace)
             storeAppendPrintf(sentry, " grace=%d", node->grace);
 
-        if (node->children != DEFAULT_EXTERNAL_ACL_CHILDREN)
-            storeAppendPrintf(sentry, " children=%d", node->children);
+        if (node->children.n_max != DEFAULT_EXTERNAL_ACL_CHILDREN)
+            storeAppendPrintf(sentry, " children-max=%d", node->children.n_max);
+
+        if (node->children.n_startup != 1)
+            storeAppendPrintf(sentry, " children-startup=%d", node->children.n_startup);
+
+        if (node->children.n_idle != (node->children.n_max + node->children.n_startup) )
+            storeAppendPrintf(sentry, " children-idle=%d", node->children.n_idle);
 
-        if (node->concurrency)
-            storeAppendPrintf(sentry, " concurrency=%d", node->concurrency);
+        if (node->children.concurrency)
+            storeAppendPrintf(sentry, " concurrency=%d", node->children.concurrency);
 
         if (node->cache)
             storeAppendPrintf(sentry, " cache=%d", node->cache_size);
@@ -514,6 +554,11 @@ dump_externalAclHelper(StoreEntry * sentry, const char *name, const external_acl
 
                 DUMP_EXT_ACL_TYPE(SRC);
                 DUMP_EXT_ACL_TYPE(SRCPORT);
+#if USE_SQUID_EUI
+                DUMP_EXT_ACL_TYPE(SRCEUI48);
+                DUMP_EXT_ACL_TYPE(SRCEUI64);
+#endif
+
                 DUMP_EXT_ACL_TYPE(MYADDR);
                 DUMP_EXT_ACL_TYPE(MYPORT);
                 DUMP_EXT_ACL_TYPE(URI);
@@ -677,9 +722,7 @@ ACLExternal::~ACLExternal()
 }
 
 static int
-aclMatchExternal(external_acl_data *acl, ACLChecklist * ch);
-static int
-aclMatchExternal(external_acl_data *acl, ACLChecklist * ch)
+aclMatchExternal(external_acl_data *acl, ACLFilledChecklist *ch)
 {
     int result;
     external_acl_entry *entry;
@@ -704,18 +747,17 @@ aclMatchExternal(external_acl_data *acl, ACLChecklist * ch)
         if (acl->def->require_auth) {
             int ti;
             /* Make sure the user is authenticated */
+            debugs(82, 3, "aclMatchExternal: " << acl->def->name << " check user authenticated.");
 
-            if ((ti = ch->authenticated()) != 1) {
+            if ((ti = AuthenticateAcl(ch)) != 1) {
                 debugs(82, 2, "aclMatchExternal: " << acl->def->name << " user not authenticated (" << ti << ")");
                 return ti;
             }
+            debugs(82, 3, "aclMatchExternal: " << acl->def->name << " user is authenticated.");
         }
 
         key = makeExternalAclKey(ch, acl);
 
-        if (acl->def->require_auth)
-            AUTHUSERREQUESTUNLOCK(ch->auth_user_request, "ACLChecklist via aclMatchExternal");
-
         if (!key) {
             /* Not sufficient data to process */
             return -1;
@@ -728,7 +770,7 @@ aclMatchExternal(external_acl_data *acl, ACLChecklist * ch)
             debugs(82, 2, "aclMatchExternal: \"" << key << "\": entry=@" <<
                    entry << ", age=" << (entry ? (long int) squid_curtime - entry->date : 0));
 
-            if (acl->def->theHelper->stats.queue_size <= acl->def->theHelper->n_running) {
+            if (acl->def->theHelper->stats.queue_size <= (int)acl->def->theHelper->childs.n_active) {
                 debugs(82, 2, "aclMatchExternal: \"" << key << "\": queueing a call.");
                 ch->changeState (ExternalACLLookup::Instance());
 
@@ -769,6 +811,9 @@ aclMatchExternal(external_acl_data *acl, ACLChecklist * ch)
 
         if (entry->log.size())
             ch->request->extacl_log = entry->log;
+
+        if (entry->message.size())
+            ch->request->extacl_message = entry->message;
     }
 
     return result;
@@ -777,7 +822,7 @@ aclMatchExternal(external_acl_data *acl, ACLChecklist * ch)
 int
 ACLExternal::match(ACLChecklist *checklist)
 {
-    return aclMatchExternal (data, checklist);
+    return aclMatchExternal (data, Filled(checklist));
 }
 
 wordlist *
@@ -811,7 +856,7 @@ external_acl_cache_touch(external_acl * def, external_acl_entry * entry)
 }
 
 static char *
-makeExternalAclKey(ACLChecklist * ch, external_acl_data * acl_data)
+makeExternalAclKey(ACLFilledChecklist * ch, external_acl_data * acl_data)
 {
     static MemBuf mb;
     char buf[256];
@@ -829,7 +874,7 @@ makeExternalAclKey(ACLChecklist * ch, external_acl_data * acl_data)
         switch (format->type) {
 
         case _external_acl_format::EXT_ACL_LOGIN:
-            assert (ch->auth_user_request);
+            assert (ch->auth_user_request != NULL);
             str = ch->auth_user_request->username();
             break;
 #if USE_IDENT
@@ -854,6 +899,18 @@ makeExternalAclKey(ACLChecklist * ch, external_acl_data * acl_data)
             str = buf;
             break;
 
+#if USE_SQUID_EUI
+        case _external_acl_format::EXT_ACL_SRCEUI48:
+            if (request->client_eui48.encode(buf, sizeof(buf)))
+                str = buf;
+            break;
+
+        case _external_acl_format::EXT_ACL_SRCEUI64:
+            if (request->client_eui64.encode(buf, sizeof(buf)))
+                str = buf;
+            break;
+#endif
+
         case _external_acl_format::EXT_ACL_MYADDR:
             str = request->my_addr.NtoA(buf, sizeof(buf));
             break;
@@ -939,8 +996,8 @@ makeExternalAclKey(ACLChecklist * ch, external_acl_data * acl_data)
 
         case _external_acl_format::EXT_ACL_USER_CERT_RAW:
 
-            if (ch->conn() != NULL) {
-                SSL *ssl = fd_table[ch->conn()->fd].ssl;
+            if (ch->conn() != NULL && Comm::IsConnOpen(ch->conn()->clientConn)) {
+                SSL *ssl = fd_table[ch->conn()->clientConn->fd].ssl;
 
                 if (ssl)
                     str = sslGetUserCertificatePEM(ssl);
@@ -950,8 +1007,8 @@ makeExternalAclKey(ACLChecklist * ch, external_acl_data * acl_data)
 
         case _external_acl_format::EXT_ACL_USER_CERTCHAIN_RAW:
 
-            if (ch->conn() != NULL) {
-                SSL *ssl = fd_table[ch->conn()->fd].ssl;
+            if (ch->conn() != NULL && Comm::IsConnOpen(ch->conn()->clientConn)) {
+                SSL *ssl = fd_table[ch->conn()->clientConn->fd].ssl;
 
                 if (ssl)
                     str = sslGetUserCertificateChainPEM(ssl);
@@ -961,8 +1018,8 @@ makeExternalAclKey(ACLChecklist * ch, external_acl_data * acl_data)
 
         case _external_acl_format::EXT_ACL_USER_CERT:
 
-            if (ch->conn() != NULL) {
-                SSL *ssl = fd_table[ch->conn()->fd].ssl;
+            if (ch->conn() != NULL && Comm::IsConnOpen(ch->conn()->clientConn)) {
+                SSL *ssl = fd_table[ch->conn()->clientConn->fd].ssl;
 
                 if (ssl)
                     str = sslGetUserAttribute(ssl, format->header);
@@ -972,8 +1029,8 @@ makeExternalAclKey(ACLChecklist * ch, external_acl_data * acl_data)
 
         case _external_acl_format::EXT_ACL_CA_CERT:
 
-            if (ch->conn() != NULL) {
-                SSL *ssl = fd_table[ch->conn()->fd].ssl;
+            if (ch->conn() != NULL && Comm::IsConnOpen(ch->conn()->clientConn)) {
+                SSL *ssl = fd_table[ch->conn()->clientConn->fd].ssl;
 
                 if (ssl)
                     str = sslGetCAAttribute(ssl, format->header);
@@ -1216,7 +1273,7 @@ externalAclHandleReply(void *data, char *reply)
 }
 
 void
-ACLExternal::ExternalAclLookup(ACLChecklist * ch, ACLExternal * me, EAH * callback, void *callback_data)
+ACLExternal::ExternalAclLookup(ACLChecklist *checklist, ACLExternal * me, EAH * callback, void *callback_data)
 {
     MemBuf buf;
     external_acl_data *acl = me->data;
@@ -1226,16 +1283,19 @@ ACLExternal::ExternalAclLookup(ACLChecklist * ch, ACLExternal * me, EAH * callba
     externalAclState *oldstate = NULL;
     bool graceful = 0;
 
+    ACLFilledChecklist *ch = Filled(checklist);
     if (acl->def->require_auth) {
         int ti;
         /* Make sure the user is authenticated */
+        debugs(82, 3, "aclMatchExternal: " << acl->def->name << " check user authenticated.");
 
-        if ((ti = ch->authenticated()) != 1) {
+        if ((ti = AuthenticateAcl(ch)) != 1) {
             debugs(82, 1, "externalAclLookup: " << acl->def->name <<
                    " user authentication failure (" << ti << ", ch=" << ch << ")");
             callback(callback_data, NULL);
             return;
         }
+        debugs(82, 3, "aclMatchExternal: " << acl->def->name << " user is authenticated.");
     }
 
     const char *key = makeExternalAclKey(ch, acl);
@@ -1302,7 +1362,7 @@ ACLExternal::ExternalAclLookup(ACLChecklist * ch, ACLExternal * me, EAH * callba
     } else {
         /* Check for queue overload */
 
-        if (def->theHelper->stats.queue_size >= def->theHelper->n_running) {
+        if (def->theHelper->stats.queue_size >= (int)def->theHelper->childs.n_running) {
             debugs(82, 1, "externalAclLookup: '" << def->name << "' queue overload (ch=" << ch << ")");
             cbdataFree(state);
             callback(callback_data, entry);
@@ -1361,10 +1421,9 @@ externalAclStats(StoreEntry * sentry)
 static void
 externalAclRegisterWithCacheManager(void)
 {
-    CacheManager::GetInstance()->
-    registerAction("external_acl",
-                   "External ACL stats",
-                   externalAclStats, 0, 1);
+    Mgr::RegisterAction("external_acl",
+                        "External ACL stats",
+                        externalAclStats, 0, 1);
 }
 
 void
@@ -1378,13 +1437,11 @@ externalAclInit(void)
             p->cache = hash_create((HASHCMP *) strcmp, hashPrime(1024), hash4);
 
         if (!p->theHelper)
-            p->theHelper = helperCreate(p->name);
+            p->theHelper = new helper(p->name);
 
         p->theHelper->cmdline = p->cmdline;
 
-        p->theHelper->n_to_start = p->children;
-
-        p->theHelper->concurrency = p->concurrency;
+        p->theHelper->childs = p->children;
 
         p->theHelper->ipc_type = IPC_TCP_SOCKET;
 
@@ -1434,7 +1491,7 @@ ExternalACLLookup::checkForAsync(ACLChecklist *checklist)const
 void
 ExternalACLLookup::LookupDone(void *data, void *result)
 {
-    ACLChecklist *checklist = (ACLChecklist *)data;
+    ACLFilledChecklist *checklist = Filled(static_cast<ACLChecklist*>(data));
     checklist->extacl_entry = cbdataReference((external_acl_entry *)result);
     checklist->asyncInProgress(false);
     checklist->changeState (ACLChecklist::NullState::Instance());