]> git.ipfire.org Git - thirdparty/squid.git/blob - src/acl/FilledChecklist.cc
SourceFormat Enforcement
[thirdparty/squid.git] / src / acl / FilledChecklist.cc
1 /*
2 * Copyright (C) 1996-2016 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 #include "squid.h"
10 #include "acl/FilledChecklist.h"
11 #include "client_side.h"
12 #include "comm/Connection.h"
13 #include "comm/forward.h"
14 #include "ExternalACLEntry.h"
15 #include "HttpReply.h"
16 #include "HttpRequest.h"
17 #include "SquidConfig.h"
18 #if USE_AUTH
19 #include "auth/AclProxyAuth.h"
20 #include "auth/UserRequest.h"
21 #endif
22
23 CBDATA_CLASS_INIT(ACLFilledChecklist);
24
25 ACLFilledChecklist::ACLFilledChecklist() :
26 dst_rdns(NULL),
27 request (NULL),
28 reply (NULL),
29 #if USE_AUTH
30 auth_user_request (NULL),
31 #endif
32 #if SQUID_SNMP
33 snmp_community(NULL),
34 #endif
35 #if USE_OPENSSL
36 sslErrors(NULL),
37 #endif
38 requestErrorType(ERR_MAX),
39 conn_(NULL),
40 fd_(-1),
41 destinationDomainChecked_(false),
42 sourceDomainChecked_(false)
43 {
44 my_addr.setEmpty();
45 src_addr.setEmpty();
46 dst_addr.setEmpty();
47 rfc931[0] = '\0';
48 }
49
50 ACLFilledChecklist::~ACLFilledChecklist()
51 {
52 assert (!asyncInProgress());
53
54 safe_free(dst_rdns); // created by xstrdup().
55
56 HTTPMSGUNLOCK(request);
57
58 HTTPMSGUNLOCK(reply);
59
60 cbdataReferenceDone(conn_);
61
62 #if USE_OPENSSL
63 cbdataReferenceDone(sslErrors);
64 #endif
65
66 debugs(28, 4, HERE << "ACLFilledChecklist destroyed " << this);
67 }
68
69 static void
70 showDebugWarning(const char *msg)
71 {
72 static uint16_t count = 0;
73 if (count > 10)
74 return;
75
76 ++count;
77 debugs(28, DBG_IMPORTANT, "ALE missing " << msg);
78 }
79
80 void
81 ACLFilledChecklist::syncAle() const
82 {
83 // make sure the ALE fields used by Format::assemble to
84 // fill the old external_acl_type codes are set if any
85 // data on them exists in the Checklist
86
87 if (!al->cache.port && conn()) {
88 showDebugWarning("listening port");
89 al->cache.port = conn()->port;
90 }
91
92 if (request) {
93 if (!al->request) {
94 showDebugWarning("HttpRequest object");
95 al->request = request;
96 HTTPMSGLOCK(al->request);
97 }
98
99 if (!al->adapted_request) {
100 showDebugWarning("adapted HttpRequest object");
101 al->adapted_request = request;
102 HTTPMSGLOCK(al->adapted_request);
103 }
104
105 if (!al->url) {
106 showDebugWarning("URL");
107 al->url = xstrdup(request->url.absolute().c_str());
108 }
109 }
110
111 if (reply && !al->reply) {
112 showDebugWarning("HttpReply object");
113 al->reply = reply;
114 HTTPMSGLOCK(al->reply);
115 }
116
117 #if USE_IDENT
118 if (*rfc931 && !al->cache.rfc931) {
119 showDebugWarning("IDENT");
120 al->cache.rfc931 = xstrdup(rfc931);
121 }
122 #endif
123 }
124
125 ConnStateData *
126 ACLFilledChecklist::conn() const
127 {
128 return conn_;
129 }
130
131 void
132 ACLFilledChecklist::conn(ConnStateData *aConn)
133 {
134 if (conn() == aConn)
135 return;
136 assert (conn() == NULL);
137 conn_ = cbdataReference(aConn);
138 }
139
140 int
141 ACLFilledChecklist::fd() const
142 {
143 return (conn_ != NULL && conn_->clientConnection != NULL) ? conn_->clientConnection->fd : fd_;
144 }
145
146 void
147 ACLFilledChecklist::fd(int aDescriptor)
148 {
149 assert(!conn() || conn()->clientConnection == NULL || conn()->clientConnection->fd == aDescriptor);
150 fd_ = aDescriptor;
151 }
152
153 bool
154 ACLFilledChecklist::destinationDomainChecked() const
155 {
156 return destinationDomainChecked_;
157 }
158
159 void
160 ACLFilledChecklist::markDestinationDomainChecked()
161 {
162 assert (!finished() && !destinationDomainChecked());
163 destinationDomainChecked_ = true;
164 }
165
166 bool
167 ACLFilledChecklist::sourceDomainChecked() const
168 {
169 return sourceDomainChecked_;
170 }
171
172 void
173 ACLFilledChecklist::markSourceDomainChecked()
174 {
175 assert (!finished() && !sourceDomainChecked());
176 sourceDomainChecked_ = true;
177 }
178
179 /*
180 * There are two common ACLFilledChecklist lifecycles paths:
181 *
182 * A) Using aclCheckFast(): The caller creates an ACLFilledChecklist object
183 * on stack and calls aclCheckFast().
184 *
185 * B) Using aclNBCheck() and callbacks: The caller allocates an
186 * ACLFilledChecklist object (via operator new) and passes it to
187 * aclNBCheck(). Control eventually passes to ACLChecklist::checkCallback(),
188 * which will invoke the callback function as requested by the
189 * original caller of aclNBCheck(). This callback function must
190 * *not* delete the list. After the callback function returns,
191 * checkCallback() will delete the list (i.e., self).
192 */
193 ACLFilledChecklist::ACLFilledChecklist(const acl_access *A, HttpRequest *http_request, const char *ident):
194 dst_rdns(NULL),
195 request(NULL),
196 reply(NULL),
197 #if USE_AUTH
198 auth_user_request(NULL),
199 #endif
200 #if SQUID_SNMP
201 snmp_community(NULL),
202 #endif
203 #if USE_OPENSSL
204 sslErrors(NULL),
205 #endif
206 requestErrorType(ERR_MAX),
207 conn_(NULL),
208 fd_(-1),
209 destinationDomainChecked_(false),
210 sourceDomainChecked_(false)
211 {
212 my_addr.setEmpty();
213 src_addr.setEmpty();
214 dst_addr.setEmpty();
215 rfc931[0] = '\0';
216
217 changeAcl(A);
218
219 if (http_request != NULL) {
220 request = http_request;
221 HTTPMSGLOCK(request);
222 #if FOLLOW_X_FORWARDED_FOR
223 if (Config.onoff.acl_uses_indirect_client)
224 src_addr = request->indirect_client_addr;
225 else
226 #endif /* FOLLOW_X_FORWARDED_FOR */
227 src_addr = request->client_addr;
228 my_addr = request->my_addr;
229
230 if (request->clientConnectionManager.valid())
231 conn(request->clientConnectionManager.get());
232 }
233
234 #if USE_IDENT
235 if (ident)
236 xstrncpy(rfc931, ident, USER_IDENT_SZ);
237 #endif
238 }
239