1 /*
2  * Copyright (C) 1996-2021 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 "AccessLogEntry.h"
11 #include "HttpReply.h"
12 #include "HttpRequest.h"
13 #include "SquidConfig.h"
14 
15 #if USE_OPENSSL
16 #include "ssl/support.h"
17 
SslDetails()18 AccessLogEntry::SslDetails::SslDetails(): user(NULL), bumpMode(::Ssl::bumpEnd)
19 {
20 }
21 #endif /* USE_OPENSSL */
22 
23 void
getLogClientIp(char * buf,size_t bufsz) const24 AccessLogEntry::getLogClientIp(char *buf, size_t bufsz) const
25 {
26     Ip::Address log_ip;
27 
28 #if FOLLOW_X_FORWARDED_FOR
29     if (Config.onoff.log_uses_indirect_client && request)
30         log_ip = request->indirect_client_addr;
31     else
32 #endif
33         if (tcpClient)
34             log_ip = tcpClient->remote;
35         else
36             log_ip = cache.caddr;
37 
38     // internally generated requests (and some ICAP) lack client IP
39     if (log_ip.isNoAddr()) {
40         strncpy(buf, "-", bufsz);
41         return;
42     }
43 
44     // Apply so-called 'privacy masking' to IPv4 clients
45     // - localhost IP is always shown in full
46     // - IPv4 clients masked with client_netmask
47     // - IPv6 clients use 'privacy addressing' instead.
48 
49     if (!log_ip.isLocalhost() && log_ip.isIPv4())
50         log_ip.applyMask(Config.Addrs.client_netmask);
51 
52     log_ip.toStr(buf, bufsz);
53 }
54 
55 SBuf
getLogMethod() const56 AccessLogEntry::getLogMethod() const
57 {
58     SBuf method;
59     if (icp.opcode)
60         method.append(icp_opcode_str[icp.opcode]);
61     else if (htcp.opcode)
62         method.append(htcp.opcode);
63     else
64         method = http.method.image();
65     return method;
66 }
67 
68 const char *
getClientIdent() const69 AccessLogEntry::getClientIdent() const
70 {
71     if (tcpClient)
72         return tcpClient->rfc931;
73 
74     if (cache.rfc931 && *cache.rfc931)
75         return cache.rfc931;
76 
77     return nullptr;
78 }
79 
80 const char *
getExtUser() const81 AccessLogEntry::getExtUser() const
82 {
83     if (request && request->extacl_user.size())
84         return request->extacl_user.termedBuf();
85 
86     if (cache.extuser && *cache.extuser)
87         return cache.extuser;
88 
89     return nullptr;
90 }
91 
~AccessLogEntry()92 AccessLogEntry::~AccessLogEntry()
93 {
94     safe_free(headers.request);
95 
96 #if USE_ADAPTATION
97     safe_free(adapt.last_meta);
98 #endif
99 
100     safe_free(headers.reply);
101 
102     safe_free(headers.adapted_request);
103     HTTPMSGUNLOCK(adapted_request);
104 
105     safe_free(lastAclName);
106 
107     HTTPMSGUNLOCK(reply);
108     HTTPMSGUNLOCK(request);
109 #if ICAP_CLIENT
110     HTTPMSGUNLOCK(icap.reply);
111     HTTPMSGUNLOCK(icap.request);
112 #endif
113 }
114 
115 const SBuf *
effectiveVirginUrl() const116 AccessLogEntry::effectiveVirginUrl() const
117 {
118     const SBuf *effectiveUrl = request ? &request->effectiveRequestUri() : &virginUrlForMissingRequest_;
119     if (effectiveUrl && !effectiveUrl->isEmpty())
120         return effectiveUrl;
121     // We can not use ALE::url here because it may contain a request URI after
122     // adaptation/redirection. When the request is missing, a non-empty ALE::url
123     // means that we missed a setVirginUrlForMissingRequest() call somewhere.
124     return nullptr;
125 }
126 
127