]> git.ipfire.org Git - thirdparty/squid.git/blame - src/acl/FilledChecklist.cc
Extracted transaction state storage and related checks from ACLChecklist into
[thirdparty/squid.git] / src / acl / FilledChecklist.cc
CommitLineData
351fe86d
AR
1#include "squid.h"
2#include "HttpRequest.h"
3#include "HttpReply.h"
4#include "client_side.h"
5#include "auth/UserRequest.h"
6#include "auth/AclProxyAuth.h"
7#include "acl/FilledChecklist.h"
8
9CBDATA_CLASS_INIT(ACLFilledChecklist);
10
11#if MOVED
12int
13ACLFilledChecklist::authenticated()
14{
15 http_hdr_type headertype;
16
17 if (NULL == request) {
18 fatal ("requiresRequest SHOULD have been true for this ACL!!");
19 return 0;
20 } else if (request->flags.accelerated) {
21 /* WWW authorization on accelerated requests */
22 headertype = HDR_AUTHORIZATION;
23 } else if (request->flags.intercepted || request->flags.spoof_client_ip) {
24 debugs(28, DBG_IMPORTANT, HERE << " authentication not applicable on intercepted requests.");
25 return -1;
26 } else {
27 /* Proxy authorization on proxy requests */
28 headertype = HDR_PROXY_AUTHORIZATION;
29 }
30
31 /* get authed here */
32 /* Note: this fills in auth_user_request when applicable */
33 /*
34 * DPW 2007-05-08
35 * tryToAuthenticateAndSetAuthUser used to try to lock and
36 * unlock auth_user_request on our behalf, but it was too
37 * ugly and hard to follow. Now we do our own locking here.
38 *
39 * I'm not sure what tryToAuthenticateAndSetAuthUser does when
40 * auth_user_request is set before calling. I'm tempted to
41 * unlock and set it to NULL, but it seems safer to save the
42 * pointer before calling and unlock it afterwards. If the
43 * pointer doesn't change then its a no-op.
44 */
45 AuthUserRequest *old_auth_user_request = auth_user_request;
46 auth_acl_t result = AuthUserRequest::tryToAuthenticateAndSetAuthUser (&auth_user_request, headertype, request, conn(), src_addr);
47 if (auth_user_request)
48 AUTHUSERREQUESTLOCK(auth_user_request, "ACLFilledChecklist");
49 AUTHUSERREQUESTUNLOCK(old_auth_user_request, "old ACLFilledChecklist");
50 switch (result) {
51
52 case AUTH_ACL_CANNOT_AUTHENTICATE:
53 debugs(28, 4, "aclMatchAcl: returning 0 user authenticated but not authorised.");
54 return 0;
55
56 case AUTH_AUTHENTICATED:
57
58 return 1;
59 break;
60
61 case AUTH_ACL_HELPER:
62 debugs(28, 4, "aclMatchAcl: returning 0 sending credentials to helper.");
63 changeState (ProxyAuthLookup::Instance());
64 return 0;
65
66 case AUTH_ACL_CHALLENGE:
67 debugs(28, 4, "aclMatchAcl: returning 0 sending authentication challenge.");
68 changeState (ProxyAuthNeeded::Instance());
69 return 0;
70
71 default:
72 fatal("unexpected authenticateAuthenticate reply\n");
73 return 0;
74 }
75}
76#endif
77
78void
79ACLFilledChecklist::checkCallback(allow_t answer)
80{
81 debugs(28, 5, "ACLFilledChecklist::checkCallback: " << this << " answer=" << answer);
82
83 /* During reconfigure, we can end up not finishing call
84 * sequences into the auth code */
85
86 if (auth_user_request) {
87 /* the filled_checklist lock */
88 AUTHUSERREQUESTUNLOCK(auth_user_request, "ACLFilledChecklist");
89 /* it might have been connection based */
90 assert(conn() != NULL);
91 /*
92 * DPW 2007-05-08
93 * yuck, this make me uncomfortable. why do this here?
94 * ConnStateData will do its own unlocking.
95 */
96 AUTHUSERREQUESTUNLOCK(conn()->auth_user_request, "conn via ACLFilledChecklist");
97 conn()->auth_type = AUTH_BROKEN;
98 }
99
100 ACLFilledChecklist::checkCallback(answer); // may delete us
101}
102
103
104void *
105ACLFilledChecklist::operator new (size_t size)
106{
107 assert (size == sizeof(ACLFilledChecklist));
108 CBDATA_INIT_TYPE(ACLFilledChecklist);
109 ACLFilledChecklist *result = cbdataAlloc(ACLFilledChecklist);
110 return result;
111}
112
113void
114ACLFilledChecklist::operator delete (void *address)
115{
116 ACLFilledChecklist *t = static_cast<ACLFilledChecklist *>(address);
117 cbdataFree(t);
118}
119
120
121ACLFilledChecklist::ACLFilledChecklist() :
122 dst_peer(NULL),
123 request (NULL),
124 reply (NULL),
125 auth_user_request (NULL),
126#if SQUID_SNMP
127 snmp_community(NULL),
128#endif
129#if USE_SSL
130 ssl_error(0),
131#endif
132 extacl_entry (NULL),
133 conn_(NULL),
134 fd_(-1),
135 destinationDomainChecked_(false),
136 sourceDomainChecked_(false)
137{
138 my_addr.SetEmpty();
139 src_addr.SetEmpty();
140 dst_addr.SetEmpty();
141 rfc931[0] = '\0';
142}
143
144
145ACLFilledChecklist::~ACLFilledChecklist()
146{
147 assert (!asyncInProgress());
148
149 if (extacl_entry)
150 cbdataReferenceDone(extacl_entry);
151
152 HTTPMSGUNLOCK(request);
153
154 HTTPMSGUNLOCK(reply);
155
156 // no auth_user_request in builds without any Authentication configured
157 if (auth_user_request)
158 AUTHUSERREQUESTUNLOCK(auth_user_request, "ACLFilledChecklist destructor");
159
160 cbdataReferenceDone(conn_);
161
162 debugs(28, 4, HERE << "ACLFilledChecklist destroyed " << this);
163}
164
165
166ConnStateData *
167ACLFilledChecklist::conn() const
168{
169 return conn_;
170}
171
172void
173ACLFilledChecklist::conn(ConnStateData *aConn)
174{
175 assert (conn() == NULL);
176 conn_ = cbdataReference(aConn);
177}
178
179int
180ACLFilledChecklist::fd() const
181{
182 return conn_ != NULL ? conn_->fd : fd_;
183}
184
185void
186ACLFilledChecklist::fd(int aDescriptor)
187{
188 assert(!conn() || conn()->fd == aDescriptor);
189 fd_ = aDescriptor;
190}
191
192bool
193ACLFilledChecklist::destinationDomainChecked() const
194{
195 return destinationDomainChecked_;
196}
197
198void
199ACLFilledChecklist::markDestinationDomainChecked()
200{
201 assert (!finished() && !destinationDomainChecked());
202 destinationDomainChecked_ = true;
203}
204
205bool
206ACLFilledChecklist::sourceDomainChecked() const
207{
208 return sourceDomainChecked_;
209}
210
211void
212ACLFilledChecklist::markSourceDomainChecked()
213{
214 assert (!finished() && !sourceDomainChecked());
215 sourceDomainChecked_ = true;
216}
217
218/*
219 * There are two common ACLFilledChecklist lifecycles paths:
220 *
221 * A) Using aclCheckFast(): The caller creates an ACLFilledChecklist object
222 * on stack and calls aclCheckFast().
223 *
224 * B) Using aclNBCheck() and callbacks: The caller allocates an
225 * ACLFilledChecklist object (via operator new) and passes it to
226 * aclNBCheck(). Control eventually passes to ACLChecklist::checkCallback(),
227 * which will invoke the callback function as requested by the
228 * original caller of aclNBCheck(). This callback function must
229 * *not* delete the list. After the callback function returns,
230 * checkCallback() will delete the list (i.e., self).
231 */
232ACLFilledChecklist::ACLFilledChecklist(const acl_access *A, HttpRequest *request, const char *ident):
233 dst_peer(NULL),
234 request(NULL),
235 reply(NULL),
236 auth_user_request(NULL),
237#if SQUID_SNMP
238 snmp_community(NULL),
239#endif
240#if USE_SSL
241 ssl_error(0),
242#endif
243 extacl_entry (NULL),
244 conn_(NULL),
245 fd_(-1),
246 destinationDomainChecked_(false),
247 sourceDomainChecked_(false)
248{
249 my_addr.SetEmpty();
250 src_addr.SetEmpty();
251 dst_addr.SetEmpty();
252 rfc931[0] = '\0';
253
254 // cbdataReferenceDone() is in either fastCheck() or the destructor
255 if (A)
256 accessList = cbdataReference(A);
257
258 if (request != NULL) {
259 request = HTTPMSGLOCK(request);
260#if FOLLOW_X_FORWARDED_FOR
261 if (Config.onoff.acl_uses_indirect_client)
262 src_addr = request->indirect_client_addr;
263 else
264#endif /* FOLLOW_X_FORWARDED_FOR */
265 src_addr = request->client_addr;
266 my_addr = request->my_addr;
267 }
268
269#if USE_IDENT
270 if (ident)
271 xstrncpy(rfc931, ident, USER_IDENT_SZ);
272#endif
273}
274