]>
Commit | Line | Data |
---|---|---|
bbc27441 | 1 | /* |
4ac4a490 | 2 | * Copyright (C) 1996-2017 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 |
24 | CBDATA_CLASS_INIT(ACLFilledChecklist); |
25 | ||
351fe86d | 26 | ACLFilledChecklist::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 |
51 | ACLFilledChecklist::~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 |
70 | static void |
71 | showDebugWarning(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 | ||
81 | void | |
82 | ACLFilledChecklist::syncAle() const | |
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"); | |
96 | al->request = request; | |
97 | HTTPMSGLOCK(al->request); | |
98 | } | |
99 | ||
100 | if (!al->adapted_request) { | |
101 | showDebugWarning("adapted HttpRequest object"); | |
102 | al->adapted_request = request; | |
103 | HTTPMSGLOCK(al->adapted_request); | |
104 | } | |
105 | ||
f57ae909 | 106 | if (al->url.isEmpty()) { |
fbbea662 | 107 | showDebugWarning("URL"); |
f57ae909 | 108 | al->url = request->url.absolute(); |
fbbea662 AJ |
109 | } |
110 | } | |
111 | ||
112 | if (reply && !al->reply) { | |
113 | showDebugWarning("HttpReply object"); | |
114 | al->reply = reply; | |
115 | HTTPMSGLOCK(al->reply); | |
116 | } | |
117 | ||
118 | #if USE_IDENT | |
c1ebba41 | 119 | if (*rfc931 && !al->cache.rfc931) { |
fbbea662 AJ |
120 | showDebugWarning("IDENT"); |
121 | al->cache.rfc931 = xstrdup(rfc931); | |
122 | } | |
123 | #endif | |
124 | } | |
125 | ||
351fe86d AR |
126 | ConnStateData * |
127 | ACLFilledChecklist::conn() const | |
128 | { | |
6cf166fc | 129 | return cbdataReferenceValid(conn_) ? conn_ : nullptr; |
351fe86d AR |
130 | } |
131 | ||
132 | void | |
133 | ACLFilledChecklist::conn(ConnStateData *aConn) | |
134 | { | |
16a16ffe CT |
135 | if (conn() == aConn) |
136 | return; | |
351fe86d AR |
137 | assert (conn() == NULL); |
138 | conn_ = cbdataReference(aConn); | |
139 | } | |
140 | ||
141 | int | |
142 | ACLFilledChecklist::fd() const | |
143 | { | |
6cf166fc EB |
144 | const auto c = conn(); |
145 | return (c && c->clientConnection) ? c->clientConnection->fd : fd_; | |
351fe86d AR |
146 | } |
147 | ||
148 | void | |
149 | ACLFilledChecklist::fd(int aDescriptor) | |
150 | { | |
6cf166fc EB |
151 | const auto c = conn(); |
152 | assert(!c || !c->clientConnection || c->clientConnection->fd == aDescriptor); | |
351fe86d AR |
153 | fd_ = aDescriptor; |
154 | } | |
155 | ||
156 | bool | |
157 | ACLFilledChecklist::destinationDomainChecked() const | |
158 | { | |
159 | return destinationDomainChecked_; | |
160 | } | |
161 | ||
162 | void | |
163 | ACLFilledChecklist::markDestinationDomainChecked() | |
164 | { | |
165 | assert (!finished() && !destinationDomainChecked()); | |
166 | destinationDomainChecked_ = true; | |
167 | } | |
168 | ||
169 | bool | |
170 | ACLFilledChecklist::sourceDomainChecked() const | |
171 | { | |
172 | return sourceDomainChecked_; | |
173 | } | |
174 | ||
175 | void | |
176 | ACLFilledChecklist::markSourceDomainChecked() | |
177 | { | |
178 | assert (!finished() && !sourceDomainChecked()); | |
179 | sourceDomainChecked_ = true; | |
180 | } | |
181 | ||
182 | /* | |
183 | * There are two common ACLFilledChecklist lifecycles paths: | |
184 | * | |
185 | * A) Using aclCheckFast(): The caller creates an ACLFilledChecklist object | |
186 | * on stack and calls aclCheckFast(). | |
187 | * | |
188 | * B) Using aclNBCheck() and callbacks: The caller allocates an | |
189 | * ACLFilledChecklist object (via operator new) and passes it to | |
190 | * aclNBCheck(). Control eventually passes to ACLChecklist::checkCallback(), | |
191 | * which will invoke the callback function as requested by the | |
192 | * original caller of aclNBCheck(). This callback function must | |
193 | * *not* delete the list. After the callback function returns, | |
194 | * checkCallback() will delete the list (i.e., self). | |
195 | */ | |
f4462b38 | 196 | ACLFilledChecklist::ACLFilledChecklist(const acl_access *A, HttpRequest *http_request, const char *ident): |
f53969cc SM |
197 | dst_rdns(NULL), |
198 | request(NULL), | |
199 | reply(NULL), | |
cc8c4af2 | 200 | #if USE_AUTH |
f53969cc | 201 | auth_user_request(NULL), |
2f1431ea | 202 | #endif |
351fe86d | 203 | #if SQUID_SNMP |
f53969cc | 204 | snmp_community(NULL), |
351fe86d | 205 | #endif |
cb4f4424 | 206 | #if USE_OPENSSL |
f53969cc | 207 | sslErrors(NULL), |
fa24d749 | 208 | #endif |
cc8c4af2 | 209 | requestErrorType(ERR_MAX), |
f53969cc SM |
210 | conn_(NULL), |
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(); | |
351fe86d | 218 | rfc931[0] = '\0'; |
af6a12ee | 219 | |
3d29e126 | 220 | changeAcl(A); |
351fe86d | 221 | |
f4462b38 | 222 | if (http_request != NULL) { |
b248c2a3 AJ |
223 | request = http_request; |
224 | HTTPMSGLOCK(request); | |
351fe86d AR |
225 | #if FOLLOW_X_FORWARDED_FOR |
226 | if (Config.onoff.acl_uses_indirect_client) | |
227 | src_addr = request->indirect_client_addr; | |
228 | else | |
229 | #endif /* FOLLOW_X_FORWARDED_FOR */ | |
230 | src_addr = request->client_addr; | |
231 | my_addr = request->my_addr; | |
16a16ffe CT |
232 | |
233 | if (request->clientConnectionManager.valid()) | |
76fae079 | 234 | conn(request->clientConnectionManager.get()); |
351fe86d AR |
235 | } |
236 | ||
237 | #if USE_IDENT | |
238 | if (ident) | |
239 | xstrncpy(rfc931, ident, USER_IDENT_SZ); | |
240 | #endif | |
241 | } | |
f53969cc | 242 |