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 #ifndef SQUID_HTTPACCESSLOGENTRY_H
10 #define SQUID_HTTPACCESSLOGENTRY_H
11 
12 #include "anyp/PortCfg.h"
13 #include "base/RefCount.h"
14 #include "comm/Connection.h"
15 #include "HierarchyLogEntry.h"
16 #include "http/ProtocolVersion.h"
17 #include "http/RequestMethod.h"
18 #include "HttpHeader.h"
19 #include "icp_opcode.h"
20 #include "ip/Address.h"
21 #include "LogTags.h"
22 #include "MessageSizes.h"
23 #include "Notes.h"
24 #include "sbuf/SBuf.h"
25 #if ICAP_CLIENT
26 #include "adaptation/icap/Elements.h"
27 #endif
28 #if USE_OPENSSL
29 #include "ssl/gadgets.h"
30 #endif
31 
32 /* forward decls */
33 class HttpReply;
34 class HttpRequest;
35 class CustomLog;
36 
37 class AccessLogEntry: public RefCountable
38 {
39 
40 public:
41     typedef RefCount<AccessLogEntry> Pointer;
42 
AccessLogEntry()43     AccessLogEntry() :
44         url(nullptr),
45         lastAclName(nullptr),
46         reply(nullptr),
47         request(nullptr),
48         adapted_request(nullptr)
49     {}
50     ~AccessLogEntry();
51 
52     /// Fetch the client IP log string into the given buffer.
53     /// Knows about several alternate locations of the IP
54     /// including indirect forwarded-for IP if configured to log that
55     void getLogClientIp(char *buf, size_t bufsz) const;
56 
57     /// Fetch the client IDENT string, or nil if none is available.
58     const char *getClientIdent() const;
59 
60     /// Fetch the external ACL provided 'user=' string, or nil if none is available.
61     const char *getExtUser() const;
62 
63     /// Fetch the transaction method string (ICP opcode, HTCP opcode or HTTP method)
64     SBuf getLogMethod() const;
65 
66     SBuf url;
67 
68     /// TCP/IP level details about the client connection
69     Comm::ConnectionPointer tcpClient;
70     // TCP/IP level details about the server or peer connection
71     // are stored in hier.tcpServer
72 
73     /** \brief This subclass holds log info for HTTP protocol
74      * \todo Inner class declarations should be moved outside
75      * \todo details of HTTP held in the parent class need moving into here.
76      */
77     class HttpDetails
78     {
79 
80     public:
HttpDetails()81         HttpDetails() :
82             method(Http::METHOD_NONE),
83             code(0),
84             content_type(NULL),
85             clientRequestSz(),
86             clientReplySz() {}
87 
88         HttpRequestMethod method;
89         int code;
90         const char *content_type;
91         AnyP::ProtocolVersion version;
92 
93         /// counters for the original request received from client
94         // TODO calculate header and payload better (by parser)
95         // XXX payload encoding overheads not calculated at all yet.
96         MessageSizes clientRequestSz;
97 
98         /// counters for the response sent to client
99         // TODO calculate header and payload better (by parser)
100         // XXX payload encoding overheads not calculated at all yet.
101         MessageSizes clientReplySz;
102 
103     } http;
104 
105     /** \brief This subclass holds log info for ICP protocol
106      * \todo Inner class declarations should be moved outside
107      */
108     class IcpDetails
109     {
110 
111     public:
IcpDetails()112         IcpDetails() : opcode(ICP_INVALID) {}
113 
114         icp_opcode opcode;
115     } icp;
116 
117     /** \brief This subclass holds log info for HTCP protocol
118      * \todo Inner class declarations should be moved outside
119      */
120     class HtcpDetails
121     {
122     public:
HtcpDetails()123         HtcpDetails() : opcode(NULL) {};
124 
125         const char *opcode;
126     } htcp;
127 
128 #if USE_OPENSSL
129     /// logging information specific to the SSL protocol
130     class SslDetails
131     {
132     public:
133         SslDetails();
134 
135         const char *user; ///< emailAddress from the SSL client certificate
136         int bumpMode; ///< whether and how the request was SslBumped
137     } ssl;
138 #endif
139 
140     /** \brief This subclass holds log info for Squid internal stats
141      * \todo Inner class declarations should be moved outside
142      * \todo some details relevant to particular protocols need shuffling to other sub-classes
143      * \todo this object field need renaming to 'squid' or something.
144      */
145     class CacheDetails
146     {
147 
148     public:
CacheDetails()149         CacheDetails() : caddr(),
150             highOffset(0),
151             objectSize(0),
152             code(LOG_TAG_NONE),
153             rfc931 (NULL),
154             extuser(NULL),
155 #if USE_OPENSSL
156             ssluser(NULL),
157 #endif
158             port(NULL)
159         {
160             caddr.setNoAddr();
161             memset(&start_time, 0, sizeof(start_time));
162             memset(&trTime, 0, sizeof(start_time));
163         }
164 
165         Ip::Address caddr;
166         int64_t highOffset;
167         int64_t objectSize;
168         LogTags code;
169         struct timeval start_time; ///< The time the master transaction started
170         struct timeval trTime; ///< The response time
171         const char *rfc931;
172         const char *extuser;
173 #if USE_OPENSSL
174 
175         const char *ssluser;
176         Security::CertPointer sslClientCert; ///< cert received from the client
177 #endif
178         AnyP::PortCfgPointer port;
179 
180     } cache;
181 
182     /** \brief This subclass holds log info for various headers in raw format
183      * \todo shuffle this to the relevant protocol section.
184      */
185     class Headers
186     {
187 
188     public:
Headers()189         Headers() : request(NULL),
190             adapted_request(NULL),
191             reply(NULL) {}
192 
193         char *request; //< virgin HTTP request headers
194 
195         char *adapted_request; //< HTTP request headers after adaptation and redirection
196 
197         char *reply;
198     } headers;
199 
200 #if USE_ADAPTATION
201     /** \brief This subclass holds general adaptation log info.
202      * \todo Inner class declarations should be moved outside.
203      */
204     class AdaptationDetails
205     {
206 
207     public:
AdaptationDetails()208         AdaptationDetails(): last_meta(NULL) {}
209 
210         /// image of the last ICAP response header or eCAP meta received
211         char *last_meta;
212     } adapt;
213 #endif
214 
215     const char *lastAclName; ///< string for external_acl_type %ACL format code
216     SBuf lastAclData; ///< string for external_acl_type %DATA format code
217 
218     HierarchyLogEntry hier;
219     HttpReply *reply;
220     HttpRequest *request; //< virgin HTTP request
221     HttpRequest *adapted_request; //< HTTP request after adaptation and redirection
222 
223     /// key:value pairs set by squid.conf note directive and
224     /// key=value pairs returned from URL rewrite/redirect helper
225     NotePairs::Pointer notes;
226 
227 #if ICAP_CLIENT
228     /** \brief This subclass holds log info for ICAP part of request
229      *  \todo Inner class declarations should be moved outside
230      */
231     class IcapLogEntry
232     {
233     public:
IcapLogEntry()234         IcapLogEntry() : reqMethod(Adaptation::methodNone), bytesSent(0), bytesRead(0),
235             bodyBytesRead(-1), request(NULL), reply(NULL),
236             outcome(Adaptation::Icap::xoUnknown), resStatus(Http::scNone)
237         {
238             memset(&trTime, 0, sizeof(trTime));
239             memset(&ioTime, 0, sizeof(ioTime));
240             memset(&processingTime, 0, sizeof(processingTime));
241         }
242 
243         Ip::Address hostAddr; ///< ICAP server IP address
244         String serviceName;        ///< ICAP service name
245         String reqUri;             ///< ICAP Request-URI
246         Adaptation::Icap::ICAP::Method reqMethod; ///< ICAP request method
247         int64_t bytesSent;       ///< number of bytes sent to ICAP server so far
248         int64_t bytesRead;       ///< number of bytes read from ICAP server so far
249         /**
250          * number of ICAP body bytes read from ICAP server or -1 for no encapsulated
251          * message data in ICAP reply (eg 204 responses)
252          */
253         int64_t bodyBytesRead;
254         HttpRequest* request;    ///< ICAP request
255         HttpReply* reply;        ///< ICAP reply
256 
257         Adaptation::Icap::XactOutcome outcome; ///< final transaction status
258         /** \brief Transaction response time.
259          * The timer starts when the ICAP transaction
260          *  is created and stops when the result of the transaction is logged
261          */
262         struct timeval trTime;
263         /** \brief Transaction I/O time.
264          * The timer starts when the first ICAP request
265          * byte is scheduled for sending and stops when the lastbyte of the
266          * ICAP response is received.
267          */
268         struct timeval ioTime;
269         Http::StatusCode resStatus;   ///< ICAP response status code
270         struct timeval processingTime;      ///< total ICAP processing time
271     }
272     icap;
273 #endif
274 
275     /// Effective URI of the received client (or equivalent) HTTP request or,
276     /// in rare cases where that information was not collected, a nil pointer.
277     /// Receiving errors are represented by "error:..." URIs.
278     /// Adaptations and redirections do not affect this URI.
279     const SBuf *effectiveVirginUrl() const;
280 
281     /// Remember Client URI (or equivalent) when there is no HttpRequest.
setVirginUrlForMissingRequest(const SBuf & vu)282     void setVirginUrlForMissingRequest(const SBuf &vu)
283     {
284         if (!request)
285             virginUrlForMissingRequest_ = vu;
286     }
287 
288 private:
289     /// Client URI (or equivalent) for effectiveVirginUrl() when HttpRequest is
290     /// missing. This member is ignored unless the request member is nil.
291     SBuf virginUrlForMissingRequest_;
292 };
293 
294 class ACLChecklist;
295 class StoreEntry;
296 
297 /* Should be in 'AccessLog.h' as the driver */
298 void accessLogLogTo(CustomLog* log, AccessLogEntry::Pointer &al, ACLChecklist* checklist = NULL);
299 void accessLogLog(AccessLogEntry::Pointer &, ACLChecklist * checklist);
300 void accessLogRotate(void);
301 void accessLogClose(void);
302 void accessLogInit(void);
303 const char *accessLogTime(time_t);
304 
305 #endif /* SQUID_HTTPACCESSLOGENTRY_H */
306 
307