]> git.ipfire.org Git - thirdparty/squid.git/blame - src/acl/FilledChecklist.cc
Simplify appending SBuf to String (#2108)
[thirdparty/squid.git] / src / acl / FilledChecklist.cc
CommitLineData
bbc27441 1/*
1f7b830e 2 * Copyright (C) 1996-2025 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"
675b8408 14#include "debug/Messages.h"
abdd93d0 15#include "ExternalACLEntry.h"
d3dddfb5 16#include "http/Stream.h"
582c2af2
FC
17#include "HttpReply.h"
18#include "HttpRequest.h"
4d5904f7 19#include "SquidConfig.h"
2f1431ea 20#if USE_AUTH
351fe86d 21#include "auth/AclProxyAuth.h"
602d9612 22#include "auth/UserRequest.h"
2f1431ea 23#endif
582c2af2 24
351fe86d
AR
25CBDATA_CLASS_INIT(ACLFilledChecklist);
26
351fe86d 27ACLFilledChecklist::ACLFilledChecklist() :
aee3523a 28 dst_rdns(nullptr),
2f1431ea 29#if USE_AUTH
aee3523a 30 auth_user_request (nullptr),
2f1431ea 31#endif
351fe86d 32#if SQUID_SNMP
aee3523a 33 snmp_community(nullptr),
fa24d749 34#endif
3248e962 35 requestErrorType(ERR_MAX),
aee3523a 36 conn_(nullptr),
f53969cc
SM
37 fd_(-1),
38 destinationDomainChecked_(false),
39 sourceDomainChecked_(false)
351fe86d 40{
4dd643d5
AJ
41 my_addr.setEmpty();
42 src_addr.setEmpty();
43 dst_addr.setEmpty();
351fe86d
AR
44}
45
351fe86d
AR
46ACLFilledChecklist::~ACLFilledChecklist()
47{
48 assert (!asyncInProgress());
49
12ef783b
AJ
50 safe_free(dst_rdns); // created by xstrdup().
51
351fe86d
AR
52 cbdataReferenceDone(conn_);
53
bf95c10a 54 debugs(28, 4, "ACLFilledChecklist destroyed " << this);
351fe86d
AR
55}
56
fbbea662
AJ
57static void
58showDebugWarning(const char *msg)
59{
60 static uint16_t count = 0;
bdd92d83 61 if (count > 10)
fbbea662
AJ
62 return;
63
64 ++count;
d816f28d 65 debugs(28, Important(58), "ERROR: ALE missing " << msg);
fbbea662
AJ
66}
67
68void
cb365059 69ACLFilledChecklist::verifyAle() const
fbbea662
AJ
70{
71 // make sure the ALE fields used by Format::assemble to
72 // fill the old external_acl_type codes are set if any
73 // data on them exists in the Checklist
74
75 if (!al->cache.port && conn()) {
76 showDebugWarning("listening port");
77 al->cache.port = conn()->port;
78 }
79
80 if (request) {
81 if (!al->request) {
82 showDebugWarning("HttpRequest object");
cb365059
EB
83 // XXX: al->request should be original,
84 // but the request may be already adapted
f05e4f37 85 al->request = request.getRaw();
fbbea662
AJ
86 HTTPMSGLOCK(al->request);
87 }
88
89 if (!al->adapted_request) {
90 showDebugWarning("adapted HttpRequest object");
f05e4f37 91 al->adapted_request = request.getRaw();
fbbea662
AJ
92 HTTPMSGLOCK(al->adapted_request);
93 }
94
f57ae909 95 if (al->url.isEmpty()) {
fbbea662 96 showDebugWarning("URL");
cb365059
EB
97 // XXX: al->url should be the request URL from client,
98 // but request->url may be different (e.g.,redirected)
57a5679b 99 al->url = request->effectiveRequestUri();
fbbea662
AJ
100 }
101 }
102
b1c2ea7a 103 if (hasReply() && !al->reply) {
fbbea662 104 showDebugWarning("HttpReply object");
b1c2ea7a 105 al->reply = reply_;
fbbea662 106 }
fbbea662
AJ
107}
108
cb365059
EB
109void
110ACLFilledChecklist::syncAle(HttpRequest *adaptedRequest, const char *logUri) const
111{
112 if (!al)
113 return;
7a023df9 114 if (adaptedRequest && !al->adapted_request) {
cb365059
EB
115 al->adapted_request = adaptedRequest;
116 HTTPMSGLOCK(al->adapted_request);
117 }
7a023df9 118 if (logUri && al->url.isEmpty())
cb365059
EB
119 al->url = logUri;
120}
121
351fe86d
AR
122ConnStateData *
123ACLFilledChecklist::conn() const
124{
6cf166fc 125 return cbdataReferenceValid(conn_) ? conn_ : nullptr;
351fe86d
AR
126}
127
128void
e227da8d 129ACLFilledChecklist::setConn(ConnStateData *aConn)
351fe86d 130{
e227da8d
AR
131 if (conn_ == aConn)
132 return; // no new information
133
134 // no conn_ replacement/removal to reduce inconsistent fill concerns
135 assert(!conn_);
136 assert(aConn);
137
138 // To reduce inconsistent fill concerns, we should be the only ones calling
139 // fillConnectionLevelDetails(). Set conn_ first so that the filling method
140 // can detect (some) direct calls from others.
351fe86d 141 conn_ = cbdataReference(aConn);
e227da8d 142 aConn->fillConnectionLevelDetails(*this);
351fe86d
AR
143}
144
145int
146ACLFilledChecklist::fd() const
147{
6cf166fc
EB
148 const auto c = conn();
149 return (c && c->clientConnection) ? c->clientConnection->fd : fd_;
351fe86d
AR
150}
151
152void
153ACLFilledChecklist::fd(int aDescriptor)
154{
6cf166fc
EB
155 const auto c = conn();
156 assert(!c || !c->clientConnection || c->clientConnection->fd == aDescriptor);
351fe86d
AR
157 fd_ = aDescriptor;
158}
159
160bool
161ACLFilledChecklist::destinationDomainChecked() const
162{
163 return destinationDomainChecked_;
164}
165
166void
167ACLFilledChecklist::markDestinationDomainChecked()
168{
169 assert (!finished() && !destinationDomainChecked());
170 destinationDomainChecked_ = true;
171}
172
173bool
174ACLFilledChecklist::sourceDomainChecked() const
175{
176 return sourceDomainChecked_;
177}
178
179void
180ACLFilledChecklist::markSourceDomainChecked()
181{
182 assert (!finished() && !sourceDomainChecked());
183 sourceDomainChecked_ = true;
184}
185
186/*
187 * There are two common ACLFilledChecklist lifecycles paths:
188 *
c56edb4a
EB
189 * "Fast" (always synchronous or "blocking"): The user constructs an
190 * ACLFilledChecklist object on stack, configures it as needed, and calls one
191 * or both of its fastCheck() methods.
351fe86d 192 *
c56edb4a
EB
193 * "Slow" (usually asynchronous or "non-blocking"): The user allocates an
194 * ACLFilledChecklist object on heap (via Make()), configures it as needed,
195 * and passes it to NonBlockingCheck() while specifying the callback function
196 * to call with check results. NonBlockingCheck() calls the callback function
197 * (if the corresponding cbdata is still valid), either immediately/directly
198 * (XXX) or eventually/asynchronously. After this callback obligations are
199 * fulfilled, checkCallback() deletes the checklist object (i.e. "this").
351fe86d 200 */
e94ff527 201ACLFilledChecklist::ACLFilledChecklist(const acl_access *A, HttpRequest *http_request):
aee3523a 202 dst_rdns(nullptr),
cc8c4af2 203#if USE_AUTH
aee3523a 204 auth_user_request(nullptr),
2f1431ea 205#endif
351fe86d 206#if SQUID_SNMP
aee3523a 207 snmp_community(nullptr),
fa24d749 208#endif
cc8c4af2 209 requestErrorType(ERR_MAX),
aee3523a 210 conn_(nullptr),
f53969cc
SM
211 fd_(-1),
212 destinationDomainChecked_(false),
213 sourceDomainChecked_(false)
351fe86d 214{
4dd643d5
AJ
215 my_addr.setEmpty();
216 src_addr.setEmpty();
217 dst_addr.setEmpty();
af6a12ee 218
3d29e126 219 changeAcl(A);
819be284 220 setRequest(http_request);
819be284 221}
351fe86d 222
819be284
EB
223void ACLFilledChecklist::setRequest(HttpRequest *httpRequest)
224{
225 assert(!request);
226 if (httpRequest) {
227 request = httpRequest;
351fe86d
AR
228#if FOLLOW_X_FORWARDED_FOR
229 if (Config.onoff.acl_uses_indirect_client)
230 src_addr = request->indirect_client_addr;
231 else
232#endif /* FOLLOW_X_FORWARDED_FOR */
233 src_addr = request->client_addr;
234 my_addr = request->my_addr;
16a16ffe 235
e227da8d
AR
236 if (const auto cmgr = request->clientConnectionManager.get())
237 setConn(cmgr);
351fe86d 238 }
819be284 239}
351fe86d 240
b1c2ea7a
AR
241void
242ACLFilledChecklist::updateAle(const AccessLogEntry::Pointer &a)
243{
244 if (!a)
245 return;
246
247 al = a; // could have been set already (to a different value)
248 if (!request)
249 setRequest(a->request);
250 updateReply(a->reply);
251}
252
253void
254ACLFilledChecklist::updateReply(const HttpReply::Pointer &r)
255{
256 if (r)
257 reply_ = r; // may already be set, including to r
258}
259