]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - src/external_acl.cc
Merge form trunk
[thirdparty/squid.git] / src / external_acl.cc
index 3c4f737084e1039befd6cbd4ac2a73592a650c55..fb090b7d5a917cf67b35c1a657b3b15dc2b42286 100644 (file)
@@ -41,7 +41,7 @@
  */
 
 #include "squid.h"
-#include "CacheManager.h"
+#include "mgr/Registration.h"
 #include "ExternalACL.h"
 #include "ExternalACLEntry.h"
 #include "auth/UserRequest.h"
 #if USE_IDENT
 #include "ident/AclIdent.h"
 #endif
+#include "ip/tools.h"
 #include "client_side.h"
+#include "comm/Connection.h"
 #include "HttpRequest.h"
 #include "HttpReply.h"
 #include "auth/Acl.h"
 #include "auth/Gadgets.h"
 #include "helper.h"
 #include "MemBuf.h"
+#include "rfc1738.h"
 #include "URLScheme.h"
 #include "wordlist.h"
 
@@ -106,9 +109,7 @@ public:
 
     wordlist *cmdline;
 
-    int children;
-
-    int concurrency;
+    HelperChildConfig children;
 
     helper *theHelper;
 
@@ -122,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 {
@@ -129,7 +136,7 @@ public:
         QUOTE_METHOD_URL
     } quote;
 
-    IpAddress local_addr;
+    Ip::Address local_addr;
 };
 
 struct _external_acl_format {
@@ -209,7 +216,7 @@ free_external_acl(void *data)
 
     if (p->theHelper) {
         helperShutdown(p->theHelper);
-        helperFree(p->theHelper);
+        delete p->theHelper;
         p->theHelper = NULL;
     }
 
@@ -294,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)
@@ -315,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) {
@@ -338,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;
         }
@@ -350,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;
 
@@ -413,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)
@@ -425,7 +448,6 @@ 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;
@@ -482,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);
@@ -719,18 +747,17 @@ aclMatchExternal(external_acl_data *acl, ACLFilledChecklist *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 = 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;
@@ -743,7 +770,7 @@ aclMatchExternal(external_acl_data *acl, ACLFilledChecklist *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());
 
@@ -784,6 +811,9 @@ aclMatchExternal(external_acl_data *acl, ACLFilledChecklist *ch)
 
         if (entry->log.size())
             ch->request->extacl_log = entry->log;
+
+        if (entry->message.size())
+            ch->request->extacl_message = entry->message;
     }
 
     return result;
@@ -844,7 +874,7 @@ makeExternalAclKey(ACLFilledChecklist * 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
@@ -966,8 +996,8 @@ makeExternalAclKey(ACLFilledChecklist * 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);
@@ -977,8 +1007,8 @@ makeExternalAclKey(ACLFilledChecklist * 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);
@@ -988,8 +1018,8 @@ makeExternalAclKey(ACLFilledChecklist * 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);
@@ -999,8 +1029,8 @@ makeExternalAclKey(ACLFilledChecklist * 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);
@@ -1257,6 +1287,7 @@ ACLExternal::ExternalAclLookup(ACLChecklist *checklist, ACLExternal * me, EAH *
     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 = AuthenticateAcl(ch)) != 1) {
             debugs(82, 1, "externalAclLookup: " << acl->def->name <<
@@ -1264,6 +1295,7 @@ ACLExternal::ExternalAclLookup(ACLChecklist *checklist, ACLExternal * me, EAH *
             callback(callback_data, NULL);
             return;
         }
+        debugs(82, 3, "aclMatchExternal: " << acl->def->name << " user is authenticated.");
     }
 
     const char *key = makeExternalAclKey(ch, acl);
@@ -1330,7 +1362,7 @@ ACLExternal::ExternalAclLookup(ACLChecklist *checklist, ACLExternal * me, EAH *
     } 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);
@@ -1389,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
@@ -1406,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;