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