]>
Commit | Line | Data |
---|---|---|
bbc27441 | 1 | /* |
b8ae064d | 2 | * Copyright (C) 1996-2023 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 | ||
f7f3304a | 9 | #include "squid.h" |
d4204018 | 10 | #include "AccessLogEntry.h" |
a8c7a110 | 11 | #include "fqdncache.h" |
582c2af2 | 12 | #include "HttpReply.h" |
d4204018 | 13 | #include "HttpRequest.h" |
49f57088 | 14 | #include "MemBuf.h" |
36c774f7 | 15 | #include "proxyp/Header.h" |
4d5904f7 | 16 | #include "SquidConfig.h" |
f3d7d090 AJ |
17 | #include "ssl/support.h" |
18 | ||
d4204018 AJ |
19 | void |
20 | AccessLogEntry::getLogClientIp(char *buf, size_t bufsz) const | |
21 | { | |
998ef291 AJ |
22 | Ip::Address log_ip; |
23 | ||
d4204018 AJ |
24 | #if FOLLOW_X_FORWARDED_FOR |
25 | if (Config.onoff.log_uses_indirect_client && request) | |
998ef291 | 26 | log_ip = request->indirect_client_addr; |
d4204018 AJ |
27 | else |
28 | #endif | |
705c36c6 | 29 | if (tcpClient) |
998ef291 | 30 | log_ip = tcpClient->remote; |
705c36c6 | 31 | else |
998ef291 AJ |
32 | log_ip = cache.caddr; |
33 | ||
705c36c6 AJ |
34 | // internally generated requests (and some ICAP) lack client IP |
35 | if (log_ip.isNoAddr()) { | |
36 | strncpy(buf, "-", bufsz); | |
37 | return; | |
38 | } | |
39 | ||
998ef291 AJ |
40 | // Apply so-called 'privacy masking' to IPv4 clients |
41 | // - localhost IP is always shown in full | |
42 | // - IPv4 clients masked with client_netmask | |
43 | // - IPv6 clients use 'privacy addressing' instead. | |
44 | ||
36c774f7 | 45 | log_ip.applyClientMask(Config.Addrs.client_netmask); |
998ef291 AJ |
46 | |
47 | log_ip.toStr(buf, bufsz); | |
d4204018 | 48 | } |
41ebd397 | 49 | |
a8c7a110 AR |
50 | const char * |
51 | AccessLogEntry::getLogClientFqdn(char * const buf, const size_t bufSize) const | |
52 | { | |
53 | // TODO: Use indirect client and tcpClient like getLogClientIp() does. | |
54 | const auto &client = cache.caddr; | |
55 | ||
56 | // internally generated (and ICAP OPTIONS) requests lack client IP | |
57 | if (client.isAnyAddr()) | |
58 | return "-"; | |
59 | ||
60 | // If we are here, Squid was configured to use %>A or equivalent. | |
61 | // Improve our chances of getting FQDN by resolving client IPs ASAP. | |
62 | Dns::ResolveClientAddressesAsap = true; // may already be true | |
63 | ||
64 | // Too late for ours, but FQDN_LOOKUP_IF_MISS might help the next caller. | |
65 | if (const auto fqdn = fqdncache_gethostbyaddr(client, FQDN_LOOKUP_IF_MISS)) | |
66 | return fqdn; // TODO: Return a safe SBuf from fqdncache_gethostbyaddr(). | |
67 | ||
68 | return client.toStr(buf, bufSize); | |
69 | } | |
70 | ||
58b148e1 AJ |
71 | SBuf |
72 | AccessLogEntry::getLogMethod() const | |
73 | { | |
ec2c4acf | 74 | static const SBuf dash("-"); |
58b148e1 AJ |
75 | SBuf method; |
76 | if (icp.opcode) | |
77 | method.append(icp_opcode_str[icp.opcode]); | |
78 | else if (htcp.opcode) | |
79 | method.append(htcp.opcode); | |
ec2c4acf | 80 | else if (http.method) |
58b148e1 | 81 | method = http.method.image(); |
ec2c4acf AR |
82 | else |
83 | method = dash; | |
58b148e1 AJ |
84 | return method; |
85 | } | |
86 | ||
75d47340 CT |
87 | void |
88 | AccessLogEntry::syncNotes(HttpRequest *req) | |
89 | { | |
90 | // XXX: auth code only has access to HttpRequest being authenticated | |
91 | // so we must handle the case where HttpRequest is set without ALE being set. | |
92 | assert(req); | |
93 | if (!notes) | |
94 | notes = req->notes(); | |
95 | else | |
96 | assert(notes == req->notes()); | |
97 | } | |
98 | ||
e3bf07f5 AJ |
99 | const char * |
100 | AccessLogEntry::getClientIdent() const | |
101 | { | |
102 | if (tcpClient) | |
103 | return tcpClient->rfc931; | |
104 | ||
105 | if (cache.rfc931 && *cache.rfc931) | |
106 | return cache.rfc931; | |
107 | ||
108 | return nullptr; | |
109 | } | |
110 | ||
111 | const char * | |
112 | AccessLogEntry::getExtUser() const | |
113 | { | |
114 | if (request && request->extacl_user.size()) | |
115 | return request->extacl_user.termedBuf(); | |
116 | ||
117 | if (cache.extuser && *cache.extuser) | |
118 | return cache.extuser; | |
119 | ||
120 | return nullptr; | |
121 | } | |
122 | ||
36c774f7 EB |
123 | AccessLogEntry::AccessLogEntry() {} |
124 | ||
41ebd397 CT |
125 | AccessLogEntry::~AccessLogEntry() |
126 | { | |
127 | safe_free(headers.request); | |
128 | ||
f5d0906a | 129 | #if USE_ADAPTATION |
41ebd397 CT |
130 | safe_free(adapt.last_meta); |
131 | #endif | |
132 | ||
41ebd397 CT |
133 | safe_free(headers.adapted_request); |
134 | HTTPMSGUNLOCK(adapted_request); | |
135 | ||
41ebd397 CT |
136 | HTTPMSGUNLOCK(request); |
137 | #if ICAP_CLIENT | |
138 | HTTPMSGUNLOCK(icap.reply); | |
139 | HTTPMSGUNLOCK(icap.request); | |
140 | #endif | |
41ebd397 | 141 | } |
f53969cc | 142 | |
ccfbe8f4 AR |
143 | ScopedId |
144 | AccessLogEntry::codeContextGist() const | |
145 | { | |
146 | if (request) { | |
147 | if (const auto &mx = request->masterXaction) | |
148 | return mx->id.detach(); | |
149 | } | |
150 | // TODO: Carefully merge ALE and MasterXaction. | |
151 | return ScopedId("ALE w/o master"); | |
152 | } | |
153 | ||
154 | std::ostream & | |
155 | AccessLogEntry::detailCodeContext(std::ostream &os) const | |
156 | { | |
157 | // TODO: Consider printing all instead of the first most important detail. | |
158 | ||
159 | if (request) { | |
160 | if (const auto &mx = request->masterXaction) | |
161 | return os << Debug::Extra << "current master transaction: " << mx->id; | |
162 | } | |
163 | ||
164 | // provide helpful details since we cannot identify the transaction exactly | |
165 | ||
166 | if (tcpClient) | |
167 | return os << Debug::Extra << "current from-client connection: " << tcpClient; | |
168 | else if (!cache.caddr.isNoAddr()) | |
169 | return os << Debug::Extra << "current client: " << cache.caddr; | |
170 | ||
171 | const auto optionalMethod = [this,&os]() { | |
172 | if (hasLogMethod()) | |
173 | os << getLogMethod() << ' '; | |
174 | return ""; | |
175 | }; | |
176 | if (const auto uri = effectiveVirginUrl()) | |
177 | return os << Debug::Extra << "current client request: " << optionalMethod() << *uri; | |
178 | else if (!url.isEmpty()) | |
179 | return os << Debug::Extra << "current request: " << optionalMethod() << url; | |
180 | else if (hasLogMethod()) | |
181 | return os << Debug::Extra << "current request method: " << getLogMethod(); | |
182 | ||
183 | return os; | |
184 | } | |
185 | ||
bec110e4 EB |
186 | const SBuf * |
187 | AccessLogEntry::effectiveVirginUrl() const | |
188 | { | |
57a5679b | 189 | const SBuf *effectiveUrl = request ? &request->effectiveRequestUri() : &virginUrlForMissingRequest_; |
bec110e4 EB |
190 | if (effectiveUrl && !effectiveUrl->isEmpty()) |
191 | return effectiveUrl; | |
192 | // We can not use ALE::url here because it may contain a request URI after | |
193 | // adaptation/redirection. When the request is missing, a non-empty ALE::url | |
194 | // means that we missed a setVirginUrlForMissingRequest() call somewhere. | |
195 | return nullptr; | |
196 | } | |
197 | ||
83b053a0 CT |
198 | const Error * |
199 | AccessLogEntry::error() const | |
200 | { | |
201 | // the order ensures that the first-imported error is returned | |
202 | if (error_) // updateError() was called before importing the request | |
203 | return &error_; | |
204 | if (request && request->error) // request was imported before updateError() | |
205 | return &request->error; | |
206 | return nullptr; // we imported no errors and no requests | |
207 | } | |
208 | ||
209 | void | |
210 | AccessLogEntry::updateError(const Error &err) | |
211 | { | |
212 | // the order ensures that error() returns the first-imported error | |
213 | if (request) | |
214 | request->error.update(err); | |
215 | else | |
216 | error_.update(err); | |
217 | } | |
218 | ||
49f57088 EB |
219 | void |
220 | AccessLogEntry::packReplyHeaders(MemBuf &mb) const | |
221 | { | |
222 | if (reply) | |
223 | reply->packHeadersUsingFastPacker(mb); | |
224 | } | |
225 |