]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - src/cache_cf.cc
SourceFormat: enforcement
[thirdparty/squid.git] / src / cache_cf.cc
index 661f41ca268d0519fab7aeb9806f43b47ca9cb04..22a8d9fe90d0cf0116f18aacac332aa84309d2a1 100644 (file)
  */
 
 #include "squid.h"
-#include "authenticate.h"
 #include "ProtoPort.h"
 #include "HttpRequestMethod.h"
-#include "AuthConfig.h"
-#include "AuthScheme.h"
+#include "auth/Config.h"
+#include "auth/Scheme.h"
 #include "CacheManager.h"
 #include "Store.h"
 #include "SwapDir.h"
 #include "ConfigParser.h"
-#include "ACL.h"
+#include "acl/Acl.h"
+#include "acl/MethodData.h"
+#include "acl/Gadgets.h"
 #include "StoreFileSystem.h"
 #include "Parsing.h"
 #include "MemBuf.h"
 #include "wordlist.h"
+#include "ident/Config.h"
 #include "ip/IpIntercept.h"
 
 #if HAVE_GLOB_H
 #include "snmp.h"
 #endif
 #if USE_SQUID_ESI
-#include "ESIParser.h"
+#include "esi/Parser.h"
 #endif
 
 #if USE_ADAPTATION
 #include "adaptation/Config.h"
 
 static void parse_adaptation_service_set_type();
+static void parse_adaptation_service_chain_type();
 static void parse_adaptation_access_type();
 
 #endif
 
 #if ICAP_CLIENT
-#include "ICAP/ICAPConfig.h"
+#include "adaptation/icap/Config.h"
 
-static void parse_icap_service_type(ICAPConfig *);
-static void dump_icap_service_type(StoreEntry *, const char *, const ICAPConfig &);
-static void free_icap_service_type(ICAPConfig *);
+static void parse_icap_service_type(Adaptation::Icap::Config *);
+static void dump_icap_service_type(StoreEntry *, const char *, const Adaptation::Icap::Config &);
+static void free_icap_service_type(Adaptation::Icap::Config *);
 static void parse_icap_class_type();
 static void parse_icap_access_type();
 
 #endif
 
 #if USE_ECAP
-#include "eCAP/Config.h"
-static void parse_ecap_service_type(Ecap::Config *);
-static void dump_ecap_service_type(StoreEntry *, const char *, const Ecap::Config &);
-static void free_ecap_service_type(Ecap::Config *);
+#include "adaptation/ecap/Config.h"
+static void parse_ecap_service_type(Adaptation::Ecap::Config *);
+static void dump_ecap_service_type(StoreEntry *, const char *, const Adaptation::Ecap::Config &);
+static void free_ecap_service_type(Adaptation::Ecap::Config *);
 #endif
 
 CBDATA_TYPE(peer);
@@ -387,6 +390,7 @@ parseConfigFile(const char *file_name)
 
     configFreeMemory();
 
+    ACLMethodData::ThePurgeCount = 0;
     default_all();
 
     err_count = parseOneConfigFile(file_name, 0);
@@ -403,7 +407,7 @@ parseConfigFile(const char *file_name)
     if (!Config.chroot_dir) {
         leave_suid();
         setUmask(Config.umask);
-        _db_init(Config.Log.log, Config.debugOptions);
+        _db_init(Debug::cache_log, Debug::debugOptions);
         enter_suid();
     }
 
@@ -426,6 +430,10 @@ configDoConfigure(void)
     memConfigure();
     /* Sanity checks */
 
+    if (Debug::rotateNumber < 0) {
+        Debug::rotateNumber = Config.Log.rotateNumber;
+    }
+
 #if SIZEOF_OFF_T <= 4
     if (Config.Store.maxObjectSize > 0x7FFF0000) {
         debugs(3, 0, "WARNING: This Squid binary can not handle files larger than 2GB. Limiting maximum_object_size to just below 2GB");
@@ -494,9 +502,6 @@ configDoConfigure(void)
     else
         Config.appendDomainLen = 0;
 
-    safe_free(debug_options)
-    debug_options = xstrdup(Config.debugOptions);
-
     if (Config.retry.maxtries > 10)
         fatal("maximum_single_addr_tries cannot be larger than 10");
 
@@ -582,6 +587,13 @@ configDoConfigure(void)
             break;
         }
 
+        for (R = Config.Refresh; R; R = R->next) {
+            if (!R->flags.ignore_must_revalidate)
+                continue;
+            debugs(22, 1, "WARNING: use of 'ignore-must-revalidate' in 'refresh_pattern' violates HTTP");
+            break;
+        }
+
         for (R = Config.Refresh; R; R = R->next) {
             if (!R->flags.ignore_private)
                 continue;
@@ -611,8 +623,9 @@ configDoConfigure(void)
 
 #endif
 
-    if (aclPurgeMethodInUse(Config.accessList.http))
-        Config2.onoff.enable_purge = 1;
+    // we enable runtime PURGE checks if there is at least one PURGE method ACL
+    // TODO: replace with a dedicated "purge" ACL option?
+    Config2.onoff.enable_purge = (ACLMethodData::ThePurgeCount > 0);
 
     Config2.onoff.mangle_request_headers = httpReqHdrManglersConfigured();
 
@@ -888,7 +901,7 @@ parseBytesUnits(const char *unit)
     if (!strncasecmp(unit, B_GBYTES_STR, strlen(B_GBYTES_STR)))
         return 1 << 30;
 
-    debugs(3, 1, "parseBytesUnits: unknown bytes unit '" << unit << "'");
+    debugs(3, DBG_CRITICAL, "WARNING: Unknown bytes unit '" << unit << "'");
 
     return 0;
 }
@@ -1490,8 +1503,7 @@ parse_cachedir(SquidConfig::_cacheSwap * swap)
     for (i = 0; i < swap->n_configured; i++) {
         assert (swap->swapDirs[i].getRaw());
 
-        if ((strcasecmp(path_str, dynamic_cast<SwapDir *>(swap->swapDirs[i].getRaw())->path)
-            ) == 0) {
+        if ((strcasecmp(path_str, dynamic_cast<SwapDir *>(swap->swapDirs[i].getRaw())->path)) == 0) {
             /* this is specific to on-fs Stores. The right
              * way to handle this is probably to have a mapping
              * from paths to stores, and have on-fs stores
@@ -1516,7 +1528,13 @@ parse_cachedir(SquidConfig::_cacheSwap * swap)
     }
 
     /* new cache_dir */
-    assert(swap->n_configured < 63);   /* 7 bits, signed */
+    if (swap->n_configured > 63) {
+        /* 7 bits, signed */
+        debugs(3, DBG_CRITICAL, "WARNING: There is a fixed maximum of 63 cache_dir entries Squid can handle.");
+        debugs(3, DBG_CRITICAL, "WARNING: '" << path_str << "' is one to many.");
+        self_destruct();
+        return;
+    }
 
     allocate_new_swapdir(swap);
 
@@ -1599,6 +1617,22 @@ dump_peer(StoreEntry * entry, const char *name, peer * p)
     }
 }
 
+/**
+ * utility function to prevent getservbyname() being called with a numeric value
+ * on Windows at least it returns garage results.
+ */
+static bool
+isUnsignedNumeric(const char *str, size_t len)
+{
+    if (len < 1) return false;
+
+    for (; len >0 && *str; str++, len--) {
+        if (! isdigit(*str))
+            return false;
+    }
+    return true;
+}
+
 /**
  \param proto  'tcp' or 'udp' for protocol
  \returns       Port the named service is supposed to be listening on.
@@ -1614,7 +1648,8 @@ GetService(const char *proto)
         return 0; /* NEVER REACHED */
     }
     /** Returns either the service port number from /etc/services */
-    port = getservbyname(token, proto);
+    if ( !isUnsignedNumeric(token, strlen(token)) )
+        port = getservbyname(token, proto);
     if (port != NULL) {
         return ntohs((u_short)port->s_port);
     }
@@ -1768,8 +1803,9 @@ parse_peer(peer ** head)
             rfc1738_unescape(p->login);
         } else if (!strncasecmp(token, "connect-timeout=", 16)) {
             p->connect_timeout = xatoi(token + 16);
+        } else if (!strncasecmp(token, "connect-fail-limit=", 19)) {
+            p->connect_fail_limit = xatoi(token + 19);
 #if USE_CACHE_DIGESTS
-
         } else if (!strncasecmp(token, "digest-url=", 11)) {
             p->digest_url = xstrdup(token + 11);
 #endif
@@ -1852,6 +1888,9 @@ parse_peer(peer ** head)
     if (p->weight < 1)
         p->weight = 1;
 
+    if (p->connect_fail_limit < 1)
+        p->connect_fail_limit = 1;
+
     p->icp.version = ICP_VERSION_CURRENT;
 
     p->test_fd = -1;
@@ -1885,27 +1924,6 @@ free_peer(peer ** P)
 
     while ((p = *P) != NULL) {
         *P = p->next;
-
-         safe_free(p->host);
-         safe_free(p->name);
-         safe_free(p->login);
-#if USE_CACHE_DIGESTS
-         safe_free(p->digest_url);
-#endif
-         safe_free(p->domain);
-#if USE_SSL
-         safe_free(p->sslcert);
-         safe_free(p->sslkey);
-         safe_free(p->ssloptions);
-         safe_free(p->sslcipher);
-         safe_free(p->sslcapath);
-         safe_free(p->sslcafile);
-         safe_free(p->sslflags);
-         safe_free(p->ssldomain);
-        if (p->sslContext)
-            SSL_CTX_free(p->sslContext);
-#endif
-
 #if USE_CACHE_DIGESTS
 
         cbdataReferenceDone(p->digest);
@@ -2227,6 +2245,9 @@ dump_refreshpattern(StoreEntry * entry, const char *name, refresh_t * head)
         if (head->flags.ignore_no_store)
             storeAppendPrintf(entry, " ignore-no-store");
 
+        if (head->flags.ignore_must_revalidate)
+            storeAppendPrintf(entry, " ignore-must-revalidate");
+
         if (head->flags.ignore_private)
             storeAppendPrintf(entry, " ignore-private");
 
@@ -2258,6 +2279,7 @@ parse_refreshpattern(refresh_t ** head)
     int ignore_reload = 0;
     int ignore_no_cache = 0;
     int ignore_no_store = 0;
+    int ignore_must_revalidate = 0;
     int ignore_private = 0;
     int ignore_auth = 0;
 #endif
@@ -2314,6 +2336,8 @@ parse_refreshpattern(refresh_t ** head)
             ignore_no_cache = 1;
         else if (!strcmp(token, "ignore-no-store"))
             ignore_no_store = 1;
+        else if (!strcmp(token, "ignore-must-revalidate"))
+            ignore_must_revalidate = 1;
         else if (!strcmp(token, "ignore-private"))
             ignore_private = 1;
         else if (!strcmp(token, "ignore-auth"))
@@ -2375,6 +2399,9 @@ parse_refreshpattern(refresh_t ** head)
     if (ignore_no_store)
         t->flags.ignore_no_store = 1;
 
+    if (ignore_must_revalidate)
+        t->flags.ignore_must_revalidate = 1;
+
     if (ignore_private)
         t->flags.ignore_private = 1;
 
@@ -2744,6 +2771,50 @@ dump_removalpolicy(StoreEntry * entry, const char *name, RemovalPolicySettings *
     storeAppendPrintf(entry, "\n");
 }
 
+static void
+free_memcachemode(SquidConfig * config)
+{
+    return;
+}
+
+static void
+parse_memcachemode(SquidConfig * config)
+{
+    char *token = strtok(NULL, w_space);
+    if (!token)
+        self_destruct();
+
+    if (strcmp(token, "always") == 0) {
+        Config.onoff.memory_cache_first = 1;
+        Config.onoff.memory_cache_disk = 1;
+    } else if (strcmp(token, "disk") == 0) {
+        Config.onoff.memory_cache_first = 0;
+        Config.onoff.memory_cache_disk = 1;
+    } else if (strncmp(token, "net", 3) == 0) {
+        Config.onoff.memory_cache_first = 1;
+        Config.onoff.memory_cache_disk = 0;
+    } else if (strcmp(token, "never") == 0) {
+        Config.onoff.memory_cache_first = 0;
+        Config.onoff.memory_cache_disk = 0;
+    } else
+        self_destruct();
+}
+
+static void
+dump_memcachemode(StoreEntry * entry, const char *name, SquidConfig &config)
+{
+    storeAppendPrintf(entry, "%s ", name);
+    if (Config.onoff.memory_cache_first && Config.onoff.memory_cache_disk)
+        storeAppendPrintf(entry, "always");
+    else if (!Config.onoff.memory_cache_first && Config.onoff.memory_cache_disk)
+        storeAppendPrintf(entry, "disk");
+    else if (Config.onoff.memory_cache_first && !Config.onoff.memory_cache_disk)
+        storeAppendPrintf(entry, "network");
+    else if (!Config.onoff.memory_cache_first && !Config.onoff.memory_cache_disk)
+        storeAppendPrintf(entry, "none");
+    storeAppendPrintf(entry, "\n");
+}
+
 #include "cf_parser.h"
 
 peer_t
@@ -2928,7 +2999,7 @@ parse_http_port_specification(http_port_list * s, char *token)
     if (NULL == host) {
         s->s.SetAnyAddr();
         s->s.SetPort(port);
-        debugs(3, 3, "http(s)_port: found Listen on wildcard address: " << s->s);
+        debugs(3, 3, "http(s)_port: found Listen on wildcard address: *:" << s->s.GetPort() );
     } else if ( s->s = host ) { /* check/parse numeric IPA */
         s->s.SetPort(port);
         debugs(3, 3, "http(s)_port: Listen on Host/IP: " << host << " --> " << s->s);
@@ -2967,6 +3038,8 @@ parse_http_port_option(http_port_list * s, char *token)
         s->accel = 1;
     } else if (strcmp(token, "accel") == 0) {
         s->accel = 1;
+    } else if (strcmp(token, "allow-direct") == 0) {
+        s->allow_direct = 1;
     } else if (strcmp(token, "no-connection-auth") == 0) {
         s->connection_auth_disabled = true;
     } else if (strcmp(token, "connection-auth=off") == 0) {
@@ -3108,10 +3181,64 @@ void
 add_http_port(char *portspec)
 {
     http_port_list *s = create_http_port(portspec);
+    // we may need to merge better of the above returns a list with clones
+    assert(s->next == NULL);
     s->next = Config.Sockaddr.http;
     Config.Sockaddr.http = s;
 }
 
+#if IPV6_SPECIAL_SPLITSTACK
+http_port_list *
+clone_http_port_list(http_port_list *a)
+{
+    http_port_list *b = new http_port_list(a->protocol);
+
+    b->s = a->s;
+    if (a->name)
+        b->name = xstrdup(a->name);
+    if (a->defaultsite)
+        b->defaultsite = xstrdup(a->defaultsite);
+
+    b->intercepted = a->intercepted;
+    b->spoof_client_ip = a->spoof_client_ip;
+    b->accel = a->accel;
+    b->allow_direct = a->allow_direct;
+    b->vhost = a->vhost;
+    b->sslBump = a->sslBump;
+    b->vport = a->vport;
+    b->connection_auth_disabled = a->connection_auth_disabled;
+    b->disable_pmtu_discovery = a->disable_pmtu_discovery;
+
+    memcpy( &(b->tcp_keepalive), &(a->tcp_keepalive), sizeof(a->tcp_keepalive));
+
+#if 0
+    // AYJ: 2009-07-18: for now SSL does not clone. Configure separate ports with IPs and SSL settings
+
+#if USE_SSL
+    // XXX: temporary hack to ease move of SSL options to http_port
+    http_port_list &http;
+
+    char *cert;
+    char *key;
+    int version;
+    char *cipher;
+    char *options;
+    char *clientca;
+    char *cafile;
+    char *capath;
+    char *crlfile;
+    char *dhfile;
+    char *sslflags;
+    char *sslcontext;
+    SSL_CTX *sslContext;
+#endif
+
+#endif /*0*/
+
+    return b;
+}
+#endif
+
 static void
 parse_http_port_list(http_port_list ** head)
 {
@@ -3129,6 +3256,15 @@ parse_http_port_list(http_port_list ** head)
         parse_http_port_option(s, token);
     }
 
+#if IPV6_SPECIAL_SPLITSTACK
+    if (s->s.IsAnyAddr()) {
+        // clone the port options from *s to *(s->next)
+        s->next = clone_http_port_list(s);
+        s->next->s.SetIPv4();
+        debugs(3, 3, "http(s)_port: clone wildcard address for split-stack: " << s->s << " and " << s->next->s);
+    }
+#endif
+
     while (*head)
         head = &(*head)->next;
 
@@ -3174,9 +3310,9 @@ dump_generic_http_port(StoreEntry * e, const char *n, const http_port_list * s)
 
     if (s->tcp_keepalive.enabled) {
         if (s->tcp_keepalive.idle || s->tcp_keepalive.interval || s->tcp_keepalive.timeout) {
-            storeAppendPrintf(e, " tcp_keepalive=%d,%d,%d", s->tcp_keepalive.idle, s->tcp_keepalive.interval, s->tcp_keepalive.timeout);
+            storeAppendPrintf(e, " tcpkeepalive=%d,%d,%d", s->tcp_keepalive.idle, s->tcp_keepalive.interval, s->tcp_keepalive.timeout);
         } else {
-            storeAppendPrintf(e, " tcp_keepalive");
+            storeAppendPrintf(e, " tcpkeepalive");
         }
     }
 
@@ -3297,9 +3433,6 @@ void
 configFreeMemory(void)
 {
     free_all();
-#if USE_SSL
-    SSL_CTX_free(Config.ssl_client.sslContext);
-#endif
 }
 
 void
@@ -3408,6 +3541,10 @@ parse_access_log(customlog ** logs)
         cl->type = CLF_SQUID;
     } else if (strcmp(logdef_name, "common") == 0) {
         cl->type = CLF_COMMON;
+#if ICAP_CLIENT
+    } else if (strcmp(logdef_name, "icap_squid") == 0) {
+        cl->type = CLF_ICAP_SQUID;
+#endif
     } else {
         debugs(3, 0, "Log format '" << logdef_name << "' is not defined");
         self_destruct();
@@ -3460,7 +3597,11 @@ dump_access_log(StoreEntry * entry, const char *name, customlog * logs)
         case CLF_COMMON:
             storeAppendPrintf(entry, "%s squid", log->filename);
             break;
-
+#if ICAP_CLIENT
+        case CLF_ICAP_SQUID:
+            storeAppendPrintf(entry, "%s icap_squid", log->filename);
+            break;
+#endif
         case CLF_AUTO:
 
             if (log->aclList)
@@ -3520,6 +3661,12 @@ parse_adaptation_service_set_type()
     Adaptation::Config::ParseServiceSet();
 }
 
+static void
+parse_adaptation_service_chain_type()
+{
+    Adaptation::Config::ParseServiceChain();
+}
+
 static void
 parse_adaptation_access_type()
 {
@@ -3532,19 +3679,19 @@ parse_adaptation_access_type()
 #if ICAP_CLIENT
 
 static void
-parse_icap_service_type(ICAPConfig * cfg)
+parse_icap_service_type(Adaptation::Icap::Config * cfg)
 {
     cfg->parseService();
 }
 
 static void
-free_icap_service_type(ICAPConfig * cfg)
+free_icap_service_type(Adaptation::Icap::Config * cfg)
 {
     cfg->freeService();
 }
 
 static void
-dump_icap_service_type(StoreEntry * entry, const char *name, const ICAPConfig &cfg)
+dump_icap_service_type(StoreEntry * entry, const char *name, const Adaptation::Icap::Config &cfg)
 {
     cfg.dumpService(entry, name);
 }
@@ -3571,19 +3718,19 @@ parse_icap_access_type()
 #if USE_ECAP
 
 static void
-parse_ecap_service_type(Ecap::Config * cfg)
+parse_ecap_service_type(Adaptation::Ecap::Config * cfg)
 {
     cfg->parseService();
 }
 
 static void
-free_ecap_service_type(Ecap::Config * cfg)
+free_ecap_service_type(Adaptation::Ecap::Config * cfg)
 {
     cfg->freeService();
 }
 
 static void
-dump_ecap_service_type(StoreEntry * entry, const char *name, const Ecap::Config &cfg)
+dump_ecap_service_type(StoreEntry * entry, const char *name, const Adaptation::Ecap::Config &cfg)
 {
     cfg.dumpService(entry, name);
 }