1 /*
2  * Copyright (C) 1996-2021 The Squid Software Foundation and contributors
3  *
4  * Squid software is distributed under GPLv2+ license and includes
5  * contributions from numerous individuals and organizations.
6  * Please see the COPYING and CONTRIBUTORS files for details.
7  */
8 
9 /* DEBUG: section 76    Internal Squid Object handling */
10 
11 #include "squid.h"
12 #include "CacheManager.h"
13 #include "comm/Connection.h"
14 #include "errorpage.h"
15 #include "HttpReply.h"
16 #include "HttpRequest.h"
17 #include "icmp/net_db.h"
18 #include "MemBuf.h"
19 #include "SquidConfig.h"
20 #include "SquidTime.h"
21 #include "Store.h"
22 #include "tools.h"
23 #include "util.h"
24 #include "wordlist.h"
25 
26 /* called when we "miss" on an internal object;
27  * generate known dynamic objects,
28  * return Http::scNotFound for others
29  */
30 void
internalStart(const Comm::ConnectionPointer & clientConn,HttpRequest * request,StoreEntry * entry)31 internalStart(const Comm::ConnectionPointer &clientConn, HttpRequest * request, StoreEntry * entry)
32 {
33     ErrorState *err;
34     const SBuf upath = request->url.path();
35     debugs(76, 3, clientConn << " requesting '" << upath << "'");
36 
37     static const SBuf netdbUri("/squid-internal-dynamic/netdb");
38     static const SBuf storeDigestUri("/squid-internal-periodic/store_digest");
39     static const SBuf mgrPfx("/squid-internal-mgr/");
40 
41     if (upath == netdbUri) {
42         netdbBinaryExchange(entry);
43     } else if (upath == storeDigestUri) {
44 #if USE_CACHE_DIGESTS
45         const char *msgbuf = "This cache is currently building its digest.\n";
46 #else
47 
48         const char *msgbuf = "This cache does not support Cache Digests.\n";
49 #endif
50 
51         HttpReply *reply = new HttpReply;
52         reply->setHeaders(Http::scNotFound, "Not Found", "text/plain", strlen(msgbuf), squid_curtime, -2);
53         entry->replaceHttpReply(reply);
54         entry->append(msgbuf, strlen(msgbuf));
55         entry->complete();
56     } else if (upath.startsWith(mgrPfx)) {
57         debugs(17, 2, "calling CacheManager due to URL-path " << mgrPfx);
58         CacheManager::GetInstance()->Start(clientConn, request, entry);
59     } else {
60         debugObj(76, 1, "internalStart: unknown request:\n",
61                  request, (ObjPackMethod) & httpRequestPack);
62         err = new ErrorState(ERR_INVALID_REQ, Http::scNotFound, request);
63         errorAppendEntry(entry, err);
64     }
65 }
66 
67 bool
internalCheck(const SBuf & urlPath)68 internalCheck(const SBuf &urlPath)
69 {
70     static const SBuf InternalPfx("/squid-internal-");
71     return urlPath.startsWith(InternalPfx);
72 }
73 
74 bool
internalStaticCheck(const SBuf & urlPath)75 internalStaticCheck(const SBuf &urlPath)
76 {
77     static const SBuf InternalStaticPfx("/squid-internal-static");
78     return urlPath.startsWith(InternalStaticPfx);
79 }
80 
81 /*
82  * makes internal url with a given host and port (remote internal url)
83  */
84 char *
internalRemoteUri(bool encrypt,const char * host,unsigned short port,const char * dir,const SBuf & name)85 internalRemoteUri(bool encrypt, const char *host, unsigned short port, const char *dir, const SBuf &name)
86 {
87     static char lc_host[SQUIDHOSTNAMELEN];
88     assert(host && !name.isEmpty());
89     /* convert host name to lower case */
90     xstrncpy(lc_host, host, SQUIDHOSTNAMELEN);
91     Tolower(lc_host);
92 
93     /* check for an IP address and format appropriately if found */
94     Ip::Address test = lc_host;
95     if ( !test.isAnyAddr() ) {
96         test.toHostStr(lc_host,SQUIDHOSTNAMELEN);
97     }
98 
99     /*
100      * append the domain in order to mirror the requests with appended
101      * domains. If that fails, just use the hostname anyway.
102      */
103     (void)urlAppendDomain(lc_host);
104 
105     /* build URI */
106     AnyP::Uri tmp(AnyP::PROTO_HTTP);
107     tmp.host(lc_host);
108     if (port)
109         tmp.port(port);
110 
111     static MemBuf mb;
112 
113     mb.reset();
114     mb.appendf("%s://" SQUIDSBUFPH, encrypt ? "https" : "http", SQUIDSBUFPRINT(tmp.authority()));
115 
116     if (dir)
117         mb.append(dir, strlen(dir));
118 
119     mb.append(name.rawContent(), name.length());
120 
121     /* return a pointer to a local static buffer */
122     return mb.buf;
123 }
124 
125 /*
126  * makes internal url with local host and port
127  */
128 char *
internalLocalUri(const char * dir,const SBuf & name)129 internalLocalUri(const char *dir, const SBuf &name)
130 {
131     // XXX: getMy*() may return https_port info, but we force http URIs
132     // because we have not checked whether the callers can handle https.
133     const bool secure = false;
134     return internalRemoteUri(secure, getMyHostname(),
135                              getMyPort(), dir, name);
136 }
137 
138 const char *
internalHostname(void)139 internalHostname(void)
140 {
141     LOCAL_ARRAY(char, host, SQUIDHOSTNAMELEN + 1);
142     xstrncpy(host, getMyHostname(), SQUIDHOSTNAMELEN);
143 
144     /* For IPv6 addresses also check for a colon */
145     if (Config.appendDomain && !strchr(host, '.') && !strchr(host, ':'))
146         strncat(host, Config.appendDomain, SQUIDHOSTNAMELEN -
147                 strlen(host) - 1);
148 
149     Tolower(host);
150 
151     return host;
152 }
153 
154 int
internalHostnameIs(const char * arg)155 internalHostnameIs(const char *arg)
156 {
157     wordlist *w;
158 
159     if (0 == strcmp(arg, internalHostname()))
160         return 1;
161 
162     for (w = Config.hostnameAliases; w; w = w->next)
163         if (0 == strcmp(arg, w->key))
164             return 1;
165 
166     return 0;
167 }
168 
169