]> git.ipfire.org Git - thirdparty/squid.git/blame - src/acl/FilledChecklist.cc
Source Format Enforcement (#763)
[thirdparty/squid.git] / src / acl / FilledChecklist.cc
CommitLineData
bbc27441 1/*
f70aedc4 2 * Copyright (C) 1996-2021 The Squid Software Foundation and contributors
bbc27441
AJ
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
582c2af2
FC
9#include "squid.h"
10#include "acl/FilledChecklist.h"
351fe86d 11#include "client_side.h"
582c2af2
FC
12#include "comm/Connection.h"
13#include "comm/forward.h"
abdd93d0 14#include "ExternalACLEntry.h"
d3dddfb5 15#include "http/Stream.h"
582c2af2
FC
16#include "HttpReply.h"
17#include "HttpRequest.h"
4d5904f7 18#include "SquidConfig.h"
2f1431ea 19#if USE_AUTH
351fe86d 20#include "auth/AclProxyAuth.h"
602d9612 21#include "auth/UserRequest.h"
2f1431ea 22#endif
582c2af2 23
351fe86d
AR
24CBDATA_CLASS_INIT(ACLFilledChecklist);
25
351fe86d 26ACLFilledChecklist::ACLFilledChecklist() :
f53969cc
SM
27 dst_rdns(NULL),
28 request (NULL),
29 reply (NULL),
2f1431ea 30#if USE_AUTH
f53969cc 31 auth_user_request (NULL),
2f1431ea 32#endif
351fe86d 33#if SQUID_SNMP
f53969cc 34 snmp_community(NULL),
351fe86d 35#endif
cb4f4424 36#if USE_OPENSSL
f53969cc 37 sslErrors(NULL),
fa24d749 38#endif
3248e962 39 requestErrorType(ERR_MAX),
f53969cc
SM
40 conn_(NULL),
41 fd_(-1),
42 destinationDomainChecked_(false),
43 sourceDomainChecked_(false)
351fe86d 44{
4dd643d5
AJ
45 my_addr.setEmpty();
46 src_addr.setEmpty();
47 dst_addr.setEmpty();
351fe86d
AR
48 rfc931[0] = '\0';
49}
50
351fe86d
AR
51ACLFilledChecklist::~ACLFilledChecklist()
52{
53 assert (!asyncInProgress());
54
12ef783b
AJ
55 safe_free(dst_rdns); // created by xstrdup().
56
351fe86d
AR
57 HTTPMSGUNLOCK(request);
58
59 HTTPMSGUNLOCK(reply);
60
351fe86d
AR
61 cbdataReferenceDone(conn_);
62
cb4f4424 63#if USE_OPENSSL
7a957a93 64 cbdataReferenceDone(sslErrors);
fa24d749 65#endif
4fb72cb9 66
351fe86d
AR
67 debugs(28, 4, HERE << "ACLFilledChecklist destroyed " << this);
68}
69
fbbea662
AJ
70static void
71showDebugWarning(const char *msg)
72{
73 static uint16_t count = 0;
bdd92d83 74 if (count > 10)
fbbea662
AJ
75 return;
76
77 ++count;
78 debugs(28, DBG_IMPORTANT, "ALE missing " << msg);
79}
80
81void
cb365059 82ACLFilledChecklist::verifyAle() const
fbbea662
AJ
83{
84 // make sure the ALE fields used by Format::assemble to
85 // fill the old external_acl_type codes are set if any
86 // data on them exists in the Checklist
87
88 if (!al->cache.port && conn()) {
89 showDebugWarning("listening port");
90 al->cache.port = conn()->port;
91 }
92
93 if (request) {
94 if (!al->request) {
95 showDebugWarning("HttpRequest object");
cb365059
EB
96 // XXX: al->request should be original,
97 // but the request may be already adapted
fbbea662
AJ
98 al->request = request;
99 HTTPMSGLOCK(al->request);
100 }
101
102 if (!al->adapted_request) {
103 showDebugWarning("adapted HttpRequest object");
104 al->adapted_request = request;
105 HTTPMSGLOCK(al->adapted_request);
106 }
107
f57ae909 108 if (al->url.isEmpty()) {
fbbea662 109 showDebugWarning("URL");
cb365059
EB
110 // XXX: al->url should be the request URL from client,
111 // but request->url may be different (e.g.,redirected)
57a5679b 112 al->url = request->effectiveRequestUri();
fbbea662
AJ
113 }
114 }
115
116 if (reply && !al->reply) {
117 showDebugWarning("HttpReply object");
118 al->reply = reply;
fbbea662
AJ
119 }
120
121#if USE_IDENT
c1ebba41 122 if (*rfc931 && !al->cache.rfc931) {
fbbea662
AJ
123 showDebugWarning("IDENT");
124 al->cache.rfc931 = xstrdup(rfc931);
125 }
126#endif
127}
128
cb365059
EB
129void
130ACLFilledChecklist::syncAle(HttpRequest *adaptedRequest, const char *logUri) const
131{
132 if (!al)
133 return;
7a023df9 134 if (adaptedRequest && !al->adapted_request) {
cb365059
EB
135 al->adapted_request = adaptedRequest;
136 HTTPMSGLOCK(al->adapted_request);
137 }
7a023df9 138 if (logUri && al->url.isEmpty())
cb365059
EB
139 al->url = logUri;
140}
141
351fe86d
AR
142ConnStateData *
143ACLFilledChecklist::conn() const
144{
6cf166fc 145 return cbdataReferenceValid(conn_) ? conn_ : nullptr;
351fe86d
AR
146}
147
148void
149ACLFilledChecklist::conn(ConnStateData *aConn)
150{
16a16ffe
CT
151 if (conn() == aConn)
152 return;
351fe86d
AR
153 assert (conn() == NULL);
154 conn_ = cbdataReference(aConn);
155}
156
157int
158ACLFilledChecklist::fd() const
159{
6cf166fc
EB
160 const auto c = conn();
161 return (c && c->clientConnection) ? c->clientConnection->fd : fd_;
351fe86d
AR
162}
163
164void
165ACLFilledChecklist::fd(int aDescriptor)
166{
6cf166fc
EB
167 const auto c = conn();
168 assert(!c || !c->clientConnection || c->clientConnection->fd == aDescriptor);
351fe86d
AR
169 fd_ = aDescriptor;
170}
171
172bool
173ACLFilledChecklist::destinationDomainChecked() const
174{
175 return destinationDomainChecked_;
176}
177
178void
179ACLFilledChecklist::markDestinationDomainChecked()
180{
181 assert (!finished() && !destinationDomainChecked());
182 destinationDomainChecked_ = true;
183}
184
185bool
186ACLFilledChecklist::sourceDomainChecked() const
187{
188 return sourceDomainChecked_;
189}
190
191void
192ACLFilledChecklist::markSourceDomainChecked()
193{
194 assert (!finished() && !sourceDomainChecked());
195 sourceDomainChecked_ = true;
196}
197
198/*
199 * There are two common ACLFilledChecklist lifecycles paths:
200 *
201 * A) Using aclCheckFast(): The caller creates an ACLFilledChecklist object
202 * on stack and calls aclCheckFast().
203 *
204 * B) Using aclNBCheck() and callbacks: The caller allocates an
205 * ACLFilledChecklist object (via operator new) and passes it to
206 * aclNBCheck(). Control eventually passes to ACLChecklist::checkCallback(),
207 * which will invoke the callback function as requested by the
208 * original caller of aclNBCheck(). This callback function must
209 * *not* delete the list. After the callback function returns,
210 * checkCallback() will delete the list (i.e., self).
211 */
f4462b38 212ACLFilledChecklist::ACLFilledChecklist(const acl_access *A, HttpRequest *http_request, const char *ident):
f53969cc
SM
213 dst_rdns(NULL),
214 request(NULL),
215 reply(NULL),
cc8c4af2 216#if USE_AUTH
f53969cc 217 auth_user_request(NULL),
2f1431ea 218#endif
351fe86d 219#if SQUID_SNMP
f53969cc 220 snmp_community(NULL),
351fe86d 221#endif
cb4f4424 222#if USE_OPENSSL
f53969cc 223 sslErrors(NULL),
fa24d749 224#endif
cc8c4af2 225 requestErrorType(ERR_MAX),
f53969cc
SM
226 conn_(NULL),
227 fd_(-1),
228 destinationDomainChecked_(false),
229 sourceDomainChecked_(false)
351fe86d 230{
4dd643d5
AJ
231 my_addr.setEmpty();
232 src_addr.setEmpty();
233 dst_addr.setEmpty();
351fe86d 234 rfc931[0] = '\0';
af6a12ee 235
3d29e126 236 changeAcl(A);
819be284
EB
237 setRequest(http_request);
238 setIdent(ident);
239}
351fe86d 240
819be284
EB
241void ACLFilledChecklist::setRequest(HttpRequest *httpRequest)
242{
243 assert(!request);
244 if (httpRequest) {
245 request = httpRequest;
b248c2a3 246 HTTPMSGLOCK(request);
351fe86d
AR
247#if FOLLOW_X_FORWARDED_FOR
248 if (Config.onoff.acl_uses_indirect_client)
249 src_addr = request->indirect_client_addr;
250 else
251#endif /* FOLLOW_X_FORWARDED_FOR */
252 src_addr = request->client_addr;
253 my_addr = request->my_addr;
16a16ffe
CT
254
255 if (request->clientConnectionManager.valid())
76fae079 256 conn(request->clientConnectionManager.get());
351fe86d 257 }
819be284 258}
351fe86d 259
819be284
EB
260void
261ACLFilledChecklist::setIdent(const char *ident)
262{
351fe86d 263#if USE_IDENT
819be284 264 assert(!rfc931[0]);
351fe86d
AR
265 if (ident)
266 xstrncpy(rfc931, ident, USER_IDENT_SZ);
267#endif
268}
f53969cc 269