]> git.ipfire.org Git - thirdparty/squid.git/blame - src/format/Format.cc
Fixed r14838 build whithout adaptation support.
[thirdparty/squid.git] / src / format / Format.cc
CommitLineData
bbc27441 1/*
ef57eb7b 2 * Copyright (C) 1996-2016 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"
38e16f92 10#include "AccessLogEntry.h"
582c2af2 11#include "client_side.h"
38e16f92
AJ
12#include "comm/Connection.h"
13#include "err_detail_type.h"
14#include "errorpage.h"
f4698e0b 15#include "fde.h"
38e16f92
AJ
16#include "format/Format.h"
17#include "format/Quoting.h"
31971e6a 18#include "format/Token.h"
95e6d864 19#include "fqdncache.h"
d3dddfb5 20#include "http/Stream.h"
38e16f92
AJ
21#include "HttpRequest.h"
22#include "MemBuf.h"
23#include "rfc1738.h"
92e3827b 24#include "security/CertError.h"
4b307ad4 25#include "security/NegotiationHistory.h"
38e16f92
AJ
26#include "SquidTime.h"
27#include "Store.h"
95d78f10 28#include "tools.h"
b1bd952a 29#include "URL.h"
cb4f4424 30#if USE_OPENSSL
2f3e52b5 31#include "ssl/ErrorDetail.h"
cedca6e7 32#include "ssl/ServerBump.h"
2f3e52b5
CT
33#endif
34
bd85ea1f
AJ
35/// Convert a string to NULL pointer if it is ""
36#define strOrNull(s) ((s)==NULL||(s)[0]=='\0'?NULL:(s))
38e16f92 37
f57ae909
NH
38const SBuf Format::Dash("-");
39
38e16f92 40Format::Format::Format(const char *n) :
f53969cc
SM
41 format(NULL),
42 next(NULL)
38e16f92
AJ
43{
44 name = xstrdup(n);
45}
46
47Format::Format::~Format()
48{
49 // erase the list without consuming stack space
50 while (next) {
51 // unlink the next entry for deletion
52 Format *temp = next;
53 next = temp->next;
54 temp->next = NULL;
55 delete temp;
56 }
57
58 // remove locals
59 xfree(name);
60 delete format;
61}
62
63bool
f4698e0b 64Format::Format::parse(const char *def)
38e16f92 65{
f4698e0b 66 const char *cur, *eos;
38e16f92
AJ
67 Token *new_lt, *last_lt;
68 enum Quoting quote = LOG_QUOTE_NONE;
69
70 debugs(46, 2, HERE << "got definition '" << def << "'");
71
72 if (format) {
73 debugs(46, DBG_IMPORTANT, "WARNING: existing format for '" << name << " " << def << "'");
74 return false;
75 }
76
77 /* very inefficent parser, but who cares, this needs to be simple */
78 /* First off, let's tokenize, we'll optimize in a second pass.
79 * A token can either be a %-prefixed sequence (usually a dynamic
80 * token but it can be an escaped sequence), or a string. */
81 cur = def;
82 eos = def + strlen(def);
83 format = new_lt = last_lt = new Token;
84 cur += new_lt->parse(cur, &quote);
85
86 while (cur < eos) {
87 new_lt = new Token;
88 last_lt->next = new_lt;
89 last_lt = new_lt;
90 cur += new_lt->parse(cur, &quote);
91 }
92
93 return true;
94}
95
96void
4e56d7f6 97Format::Format::dump(StoreEntry * entry, const char *directiveName, bool eol) const
38e16f92
AJ
98{
99 debugs(46, 4, HERE);
100
101 // loop rather than recursing to conserve stack space.
4e56d7f6 102 for (const Format *fmt = this; fmt; fmt = fmt->next) {
5f621cd0 103 debugs(46, 3, HERE << "Dumping format definition for " << fmt->name);
4e56d7f6
AJ
104 if (directiveName)
105 storeAppendPrintf(entry, "%s %s ", directiveName, fmt->name);
38e16f92 106
5f621cd0 107 for (Token *t = fmt->format; t; t = t->next) {
38e16f92
AJ
108 if (t->type == LFT_STRING)
109 storeAppendPrintf(entry, "%s", t->data.string);
110 else {
111 char argbuf[256];
112 char *arg = NULL;
113 ByteCode_t type = t->type;
114
115 switch (type) {
f53969cc 116 /* special cases */
38e16f92
AJ
117
118 case LFT_STRING:
119 break;
120#if USE_ADAPTATION
121 case LFT_ADAPTATION_LAST_HEADER_ELEM:
122#endif
123#if ICAP_CLIENT
124 case LFT_ICAP_REQ_HEADER_ELEM:
125 case LFT_ICAP_REP_HEADER_ELEM:
126#endif
127 case LFT_REQUEST_HEADER_ELEM:
128 case LFT_ADAPTED_REQUEST_HEADER_ELEM:
129 case LFT_REPLY_HEADER_ELEM:
130
131 if (t->data.header.separator != ',')
132 snprintf(argbuf, sizeof(argbuf), "%s:%c%s", t->data.header.header, t->data.header.separator, t->data.header.element);
133 else
134 snprintf(argbuf, sizeof(argbuf), "%s:%s", t->data.header.header, t->data.header.element);
135
136 arg = argbuf;
137
138 switch (type) {
139 case LFT_REQUEST_HEADER_ELEM:
140 type = LFT_REQUEST_HEADER_ELEM; // XXX: remove _ELEM?
141 break;
142 case LFT_ADAPTED_REQUEST_HEADER_ELEM:
143 type = LFT_ADAPTED_REQUEST_HEADER_ELEM; // XXX: remove _ELEM?
144 break;
145 case LFT_REPLY_HEADER_ELEM:
146 type = LFT_REPLY_HEADER_ELEM; // XXX: remove _ELEM?
147 break;
148#if USE_ADAPTATION
149 case LFT_ADAPTATION_LAST_HEADER_ELEM:
150 type = LFT_ADAPTATION_LAST_HEADER;
151 break;
152#endif
153#if ICAP_CLIENT
154 case LFT_ICAP_REQ_HEADER_ELEM:
155 type = LFT_ICAP_REQ_HEADER;
156 break;
157 case LFT_ICAP_REP_HEADER_ELEM:
158 type = LFT_ICAP_REP_HEADER;
159 break;
160#endif
161 default:
162 break;
163 }
164
165 break;
166
167 case LFT_REQUEST_ALL_HEADERS:
168 case LFT_ADAPTED_REQUEST_ALL_HEADERS:
169 case LFT_REPLY_ALL_HEADERS:
170
171#if USE_ADAPTATION
172 case LFT_ADAPTATION_LAST_ALL_HEADERS:
173#endif
174#if ICAP_CLIENT
175 case LFT_ICAP_REQ_ALL_HEADERS:
176 case LFT_ICAP_REP_ALL_HEADERS:
177#endif
178
179 switch (type) {
180 case LFT_REQUEST_ALL_HEADERS:
181 type = LFT_REQUEST_HEADER;
182 break;
183 case LFT_ADAPTED_REQUEST_ALL_HEADERS:
184 type = LFT_ADAPTED_REQUEST_HEADER;
185 break;
186 case LFT_REPLY_ALL_HEADERS:
187 type = LFT_REPLY_HEADER;
188 break;
189#if USE_ADAPTATION
190 case LFT_ADAPTATION_LAST_ALL_HEADERS:
191 type = LFT_ADAPTATION_LAST_HEADER;
192 break;
193#endif
194#if ICAP_CLIENT
195 case LFT_ICAP_REQ_ALL_HEADERS:
196 type = LFT_ICAP_REQ_HEADER;
197 break;
198 case LFT_ICAP_REP_ALL_HEADERS:
199 type = LFT_ICAP_REP_HEADER;
200 break;
201#endif
202 default:
203 break;
204 }
205
206 break;
207
208 default:
209 if (t->data.string)
210 arg = t->data.string;
211
212 break;
213 }
214
215 entry->append("%", 1);
216
217 switch (t->quote) {
218
219 case LOG_QUOTE_QUOTES:
220 entry->append("\"", 1);
221 break;
222
223 case LOG_QUOTE_MIMEBLOB:
224 entry->append("[", 1);
225 break;
226
227 case LOG_QUOTE_URL:
228 entry->append("#", 1);
229 break;
230
231 case LOG_QUOTE_RAW:
232 entry->append("'", 1);
233 break;
234
95d78f10
AJ
235 case LOG_QUOTE_SHELL:
236 entry->append("/", 1);
237 break;
238
38e16f92
AJ
239 case LOG_QUOTE_NONE:
240 break;
241 }
242
243 if (t->left)
244 entry->append("-", 1);
245
246 if (t->zero)
247 entry->append("0", 1);
248
8846a2b4
CT
249 if (t->widthMin >= 0)
250 storeAppendPrintf(entry, "%d", t->widthMin);
38e16f92 251
8846a2b4
CT
252 if (t->widthMax >= 0)
253 storeAppendPrintf(entry, ".%d", t->widthMax);
38e16f92
AJ
254
255 if (arg)
256 storeAppendPrintf(entry, "{%s}", arg);
257
aa99e35e 258 storeAppendPrintf(entry, "%s", t->label);
38e16f92
AJ
259
260 if (t->space)
261 entry->append(" ", 1);
262 }
263 }
264
4e56d7f6
AJ
265 if (eol)
266 entry->append("\n", 1);
38e16f92
AJ
267 }
268
269}
270
271static void
272log_quoted_string(const char *str, char *out)
273{
274 char *p = out;
275
276 while (*str) {
277 int l = strcspn(str, "\"\\\r\n\t");
278 memcpy(p, str, l);
279 str += l;
280 p += l;
281
282 switch (*str) {
283
284 case '\0':
285 break;
286
287 case '\r':
a38ec4b1
FC
288 *p = '\\';
289 ++p;
290 *p = 'r';
291 ++p;
cb4185f1 292 ++str;
38e16f92
AJ
293 break;
294
295 case '\n':
a38ec4b1
FC
296 *p = '\\';
297 ++p;
298 *p = 'n';
299 ++p;
cb4185f1 300 ++str;
38e16f92
AJ
301 break;
302
303 case '\t':
a38ec4b1
FC
304 *p = '\\';
305 ++p;
306 *p = 't';
307 ++p;
cb4185f1 308 ++str;
38e16f92
AJ
309 break;
310
311 default:
a38ec4b1
FC
312 *p = '\\';
313 ++p;
314 *p = *str;
315 ++p;
cb4185f1 316 ++str;
38e16f92
AJ
317 break;
318 }
319 }
320
cb4185f1 321 *p = '\0';
38e16f92
AJ
322}
323
7598eb63
CT
324#if USE_OPENSSL
325static char *
13cd7dee 326sslErrorName(Security::ErrorCode err, char *buf, size_t size)
7598eb63
CT
327{
328 snprintf(buf, size, "SSL_ERR=%d", err);
329 return buf;
330}
331#endif
332
bd59d61c
EB
333static const HttpMsg *
334actualReplyHeader(const AccessLogEntry::Pointer &al)
335{
336 const HttpMsg *msg = al->reply;
25dadb98 337#if USE_ADAPTATION
bd59d61c
EB
338 if (!msg && al->icap.reqMethod == Adaptation::methodReqmod)
339 msg = al->adapted_request;
25dadb98 340#endif
bd59d61c
EB
341 return msg;
342}
343
344static const HttpMsg *
345actualRequestHeader(const AccessLogEntry::Pointer &al)
346{
25dadb98 347#if USE_ADAPTATION
bd59d61c
EB
348 if (al->icap.reqMethod == Adaptation::methodRespmod) {
349 // XXX: for now AccessLogEntry lacks virgin response headers
350 return nullptr;
351 }
25dadb98 352#endif
bd59d61c
EB
353 return al->request;
354}
355
38e16f92 356void
f4698e0b 357Format::Format::assemble(MemBuf &mb, const AccessLogEntry::Pointer &al, int logSequenceNumber) const
38e16f92
AJ
358{
359 char tmp[1024];
360 String sb;
361
f53969cc 362 for (Token *fmt = format; fmt != NULL; fmt = fmt->next) { /* for each token */
38e16f92
AJ
363 const char *out = NULL;
364 int quote = 0;
365 long int outint = 0;
366 int doint = 0;
367 int dofree = 0;
368 int64_t outoff = 0;
369 int dooff = 0;
01bd87d8
CT
370 struct timeval outtv = {0, 0};
371 int doMsec = 0;
372 int doSec = 0;
38e16f92
AJ
373
374 switch (fmt->type) {
375
376 case LFT_NONE:
377 out = "";
378 break;
379
380 case LFT_STRING:
381 out = fmt->data.string;
382 break;
383
384 case LFT_CLIENT_IP_ADDRESS:
d4204018
AJ
385 al->getLogClientIp(tmp, sizeof(tmp));
386 out = tmp;
38e16f92
AJ
387 break;
388
389 case LFT_CLIENT_FQDN:
4dd643d5 390 if (al->cache.caddr.isAnyAddr()) // e.g., ICAP OPTIONS lack client
38e16f92
AJ
391 out = "-";
392 else
393 out = fqdncache_gethostbyaddr(al->cache.caddr, FQDN_LOOKUP_IF_MISS);
394 if (!out) {
4dd643d5 395 out = al->cache.caddr.toStr(tmp,1024);
38e16f92
AJ
396 }
397
398 break;
399
400 case LFT_CLIENT_PORT:
401 if (al->request) {
4dd643d5 402 outint = al->request->client_addr.port();
38e16f92
AJ
403 doint = 1;
404 }
405 break;
406
38e16f92 407 case LFT_CLIENT_EUI:
8652f8e7 408#if USE_SQUID_EUI
38e16f92
AJ
409 // TODO make the ACL checklist have a direct link to any TCP details.
410 if (al->request && al->request->clientConnectionManager.valid() && al->request->clientConnectionManager->clientConnection != NULL) {
4dd643d5 411 if (al->request->clientConnectionManager->clientConnection->remote.isIPv4())
38e16f92
AJ
412 al->request->clientConnectionManager->clientConnection->remoteEui48.encode(tmp, 1024);
413 else
414 al->request->clientConnectionManager->clientConnection->remoteEui64.encode(tmp, 1024);
415 out = tmp;
416 }
38e16f92 417#endif
8652f8e7 418 break;
38e16f92 419
4e56d7f6 420 case LFT_EXT_ACL_CLIENT_EUI48:
38d7fa02 421#if USE_SQUID_EUI
4e56d7f6
AJ
422 if (al->request && al->request->clientConnectionManager.valid() &&
423 al->request->clientConnectionManager->clientConnection != NULL &&
424 al->request->clientConnectionManager->clientConnection->remote.isIPv4()) {
425 al->request->clientConnectionManager->clientConnection->remoteEui48.encode(tmp, 1024);
426 out = tmp;
427 }
38d7fa02 428#endif
4e56d7f6
AJ
429 break;
430
431 case LFT_EXT_ACL_CLIENT_EUI64:
38d7fa02 432#if USE_SQUID_EUI
4e56d7f6
AJ
433 if (al->request && al->request->clientConnectionManager.valid() &&
434 al->request->clientConnectionManager->clientConnection != NULL &&
435 !al->request->clientConnectionManager->clientConnection->remote.isIPv4()) {
436 al->request->clientConnectionManager->clientConnection->remoteEui64.encode(tmp, 1024);
437 out = tmp;
438 }
4e56d7f6 439#endif
38d7fa02 440 break;
4e56d7f6 441
8652f8e7
AJ
442 case LFT_SERVER_IP_ADDRESS:
443 if (al->hier.tcpServer != NULL) {
4dd643d5 444 out = al->hier.tcpServer->remote.toStr(tmp,sizeof(tmp));
8652f8e7
AJ
445 }
446 break;
38e16f92 447
8652f8e7 448 case LFT_SERVER_FQDN_OR_PEER_NAME:
38e16f92 449 out = al->hier.host;
38e16f92
AJ
450 break;
451
8652f8e7
AJ
452 case LFT_SERVER_PORT:
453 if (al->hier.tcpServer != NULL) {
4dd643d5 454 outint = al->hier.tcpServer->remote.port();
8652f8e7
AJ
455 doint = 1;
456 }
457 break;
38e16f92 458
28417506
CT
459 case LFT_LOCAL_LISTENING_IP: {
460 // avoid logging a dash if we have reliable info
47176c0b 461 const bool interceptedAtKnownPort = al->request ?
0d901ef4 462 (al->request->flags.interceptTproxy ||
fa720bfb 463 al->request->flags.intercepted) && al->cache.port != NULL :
47176c0b 464 false;
28417506 465 if (interceptedAtKnownPort) {
4dd643d5 466 const bool portAddressConfigured = !al->cache.port->s.isAnyAddr();
28417506 467 if (portAddressConfigured)
4dd643d5 468 out = al->cache.port->s.toStr(tmp, sizeof(tmp));
28417506 469 } else if (al->tcpClient != NULL)
4dd643d5 470 out = al->tcpClient->local.toStr(tmp, sizeof(tmp));
28417506
CT
471 }
472 break;
473
8652f8e7 474 case LFT_CLIENT_LOCAL_IP:
a14f38d0 475 if (al->tcpClient != NULL) {
4dd643d5 476 out = al->tcpClient->local.toStr(tmp,sizeof(tmp));
38e16f92 477 }
38e16f92
AJ
478 break;
479
f123f5e9
CT
480 case LFT_CLIENT_LOCAL_TOS:
481 if (al->tcpClient != NULL) {
482 snprintf(tmp, sizeof(tmp), "0x%x", (uint32_t)al->tcpClient->tos);
483 out = tmp;
484 }
485 break;
486
487 case LFT_CLIENT_LOCAL_NFMARK:
488 if (al->tcpClient != NULL) {
489 snprintf(tmp, sizeof(tmp), "0x%x", al->tcpClient->nfmark);
490 out = tmp;
491 }
492 break;
493
28417506 494 case LFT_LOCAL_LISTENING_PORT:
fa720bfb 495 if (al->cache.port != NULL) {
4dd643d5 496 outint = al->cache.port->s.port();
28417506 497 doint = 1;
fbbea662
AJ
498 } else if (al->request) {
499 outint = al->request->my_addr.port();
500 doint = 1;
28417506
CT
501 }
502 break;
503
8652f8e7 504 case LFT_CLIENT_LOCAL_PORT:
a14f38d0 505 if (al->tcpClient != NULL) {
4dd643d5 506 outint = al->tcpClient->local.port();
38e16f92
AJ
507 doint = 1;
508 }
38e16f92
AJ
509 break;
510
8652f8e7
AJ
511 case LFT_SERVER_LOCAL_IP_OLD_27:
512 case LFT_SERVER_LOCAL_IP:
a14f38d0 513 if (al->hier.tcpServer != NULL) {
4dd643d5 514 out = al->hier.tcpServer->local.toStr(tmp,sizeof(tmp));
38e16f92
AJ
515 }
516 break;
517
8652f8e7 518 case LFT_SERVER_LOCAL_PORT:
a14f38d0 519 if (al->hier.tcpServer != NULL) {
4dd643d5 520 outint = al->hier.tcpServer->local.port();
38e16f92
AJ
521 doint = 1;
522 }
523
524 break;
525
f123f5e9
CT
526 case LFT_SERVER_LOCAL_TOS:
527 if (al->hier.tcpServer != NULL) {
528 snprintf(tmp, sizeof(tmp), "0x%x", (uint32_t)al->hier.tcpServer->tos);
529 out = tmp;
530 }
531 break;
532
533 case LFT_SERVER_LOCAL_NFMARK:
534 if (al->hier.tcpServer != NULL) {
535 snprintf(tmp, sizeof(tmp), "0x%x", al->hier.tcpServer->nfmark);
536 out = tmp;
537 }
538 break;
539
38e16f92
AJ
540 case LFT_TIME_SECONDS_SINCE_EPOCH:
541 // some platforms store time in 32-bit, some 64-bit...
542 outoff = static_cast<int64_t>(current_time.tv_sec);
543 dooff = 1;
544 break;
545
546 case LFT_TIME_SUBSECOND:
547 outint = current_time.tv_usec / fmt->divisor;
548 doint = 1;
549 break;
550
38e16f92
AJ
551 case LFT_TIME_LOCALTIME:
552
553 case LFT_TIME_GMT: {
554 const char *spec;
555
556 struct tm *t;
b22c1ad3 557 spec = fmt->data.string;
38e16f92
AJ
558
559 if (fmt->type == LFT_TIME_LOCALTIME) {
560 if (!spec)
561 spec = "%d/%b/%Y:%H:%M:%S %z";
562 t = localtime(&squid_curtime);
563 } else {
564 if (!spec)
565 spec = "%d/%b/%Y:%H:%M:%S";
566
567 t = gmtime(&squid_curtime);
568 }
569
570 strftime(tmp, sizeof(tmp), spec, t);
571
572 out = tmp;
573 }
574
575 break;
576
01bd87d8
CT
577 case LFT_TIME_START:
578 outtv = al->cache.start_time;
579 doSec = 1;
f53969cc 580 break;
af0ded40 581
38e16f92 582 case LFT_TIME_TO_HANDLE_REQUEST:
01bd87d8
CT
583 outtv = al->cache.trTime;
584 doMsec = 1;
38e16f92
AJ
585 break;
586
587 case LFT_PEER_RESPONSE_TIME:
01bd87d8 588 if (al->hier.peer_response_time.tv_sec == -1) {
38e16f92
AJ
589 out = "-";
590 } else {
01bd87d8
CT
591 outtv = al->hier.peer_response_time;
592 doMsec = 1;
38e16f92
AJ
593 }
594 break;
595
16b70e2a 596 case LFT_TOTAL_SERVER_SIDE_RESPONSE_TIME: {
01bd87d8
CT
597 timeval total_response_time;
598 al->hier.totalResponseTime(total_response_time);
599 if (total_response_time.tv_sec == -1) {
38e16f92
AJ
600 out = "-";
601 } else {
01bd87d8
CT
602 outtv = total_response_time;
603 doMsec = 1;
38e16f92 604 }
16b70e2a
CT
605 }
606 break;
38e16f92
AJ
607
608 case LFT_DNS_WAIT_TIME:
609 if (al->request && al->request->dnsWait >= 0) {
01bd87d8
CT
610 // TODO: microsecond precision for dns wait time.
611 // Convert miliseconds to timeval struct:
612 outtv.tv_sec = al->request->dnsWait / 1000;
613 outtv.tv_usec = (al->request->dnsWait % 1000) * 1000;
614 doMsec = 1;
38e16f92
AJ
615 }
616 break;
617
618 case LFT_REQUEST_HEADER:
bd59d61c
EB
619 if (const HttpMsg *msg = actualRequestHeader(al))
620 sb = msg->header.getByName(fmt->data.header.header);
38e16f92
AJ
621
622 out = sb.termedBuf();
623
624 quote = 1;
625
626 break;
627
628 case LFT_ADAPTED_REQUEST_HEADER:
629
38d92afa 630 if (al->adapted_request)
38e16f92
AJ
631 sb = al->adapted_request->header.getByName(fmt->data.header.header);
632
633 out = sb.termedBuf();
634
635 quote = 1;
636
637 break;
638
bd59d61c
EB
639 case LFT_REPLY_HEADER: {
640 if (const HttpMsg *msg = actualReplyHeader(al))
641 sb = msg->header.getByName(fmt->data.header.header);
38e16f92
AJ
642
643 out = sb.termedBuf();
644
645 quote = 1;
bd59d61c
EB
646 }
647 break;
38e16f92
AJ
648
649#if USE_ADAPTATION
31971e6a 650 case LFT_ADAPTATION_SUM_XACT_TIMES:
38e16f92
AJ
651 if (al->request) {
652 Adaptation::History::Pointer ah = al->request->adaptHistory();
653 if (ah != NULL)
654 ah->sumLogString(fmt->data.string, sb);
655 out = sb.termedBuf();
656 }
657 break;
658
31971e6a 659 case LFT_ADAPTATION_ALL_XACT_TIMES:
38e16f92
AJ
660 if (al->request) {
661 Adaptation::History::Pointer ah = al->request->adaptHistory();
662 if (ah != NULL)
663 ah->allLogString(fmt->data.string, sb);
664 out = sb.termedBuf();
665 }
666 break;
667
668 case LFT_ADAPTATION_LAST_HEADER:
669 if (al->request) {
670 const Adaptation::History::Pointer ah = al->request->adaptHistory();
671 if (ah != NULL) // XXX: add adapt::<all_h but use lastMeta here
672 sb = ah->allMeta.getByName(fmt->data.header.header);
673 }
674
675 // XXX: here and elsewhere: move such code inside the if guard
676 out = sb.termedBuf();
677
678 quote = 1;
679
680 break;
681
682 case LFT_ADAPTATION_LAST_HEADER_ELEM:
683 if (al->request) {
684 const Adaptation::History::Pointer ah = al->request->adaptHistory();
685 if (ah != NULL) // XXX: add adapt::<all_h but use lastMeta here
686 sb = ah->allMeta.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
687 }
688
689 out = sb.termedBuf();
690
691 quote = 1;
692
693 break;
694
695 case LFT_ADAPTATION_LAST_ALL_HEADERS:
696 out = al->adapt.last_meta;
697
698 quote = 1;
699
700 break;
701#endif
702
703#if ICAP_CLIENT
704 case LFT_ICAP_ADDR:
705 if (!out)
4dd643d5 706 out = al->icap.hostAddr.toStr(tmp,1024);
38e16f92
AJ
707 break;
708
709 case LFT_ICAP_SERV_NAME:
710 out = al->icap.serviceName.termedBuf();
711 break;
712
713 case LFT_ICAP_REQUEST_URI:
714 out = al->icap.reqUri.termedBuf();
715 break;
716
717 case LFT_ICAP_REQUEST_METHOD:
718 out = Adaptation::Icap::ICAP::methodStr(al->icap.reqMethod);
719 break;
720
721 case LFT_ICAP_BYTES_SENT:
722 outoff = al->icap.bytesSent;
723 dooff = 1;
724 break;
725
726 case LFT_ICAP_BYTES_READ:
727 outoff = al->icap.bytesRead;
728 dooff = 1;
729 break;
730
731 case LFT_ICAP_BODY_BYTES_READ:
732 if (al->icap.bodyBytesRead >= 0) {
733 outoff = al->icap.bodyBytesRead;
734 dooff = 1;
735 }
736 // else if icap.bodyBytesRead < 0, we do not have any http data,
737 // so just print a "-" (204 responses etc)
738 break;
739
740 case LFT_ICAP_REQ_HEADER:
741 if (NULL != al->icap.request) {
742 sb = al->icap.request->header.getByName(fmt->data.header.header);
743 out = sb.termedBuf();
744 quote = 1;
745 }
746 break;
747
748 case LFT_ICAP_REQ_HEADER_ELEM:
7f0ceafc 749 if (al->icap.request)
38e16f92
AJ
750 sb = al->icap.request->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
751
752 out = sb.termedBuf();
753
754 quote = 1;
755
756 break;
757
758 case LFT_ICAP_REQ_ALL_HEADERS:
759 if (al->icap.request) {
760 HttpHeaderPos pos = HttpHeaderInitPos;
761 while (const HttpHeaderEntry *e = al->icap.request->header.getEntry(&pos)) {
762 sb.append(e->name);
763 sb.append(": ");
764 sb.append(e->value);
765 sb.append("\r\n");
766 }
767 out = sb.termedBuf();
768 quote = 1;
769 }
770 break;
771
772 case LFT_ICAP_REP_HEADER:
773 if (NULL != al->icap.reply) {
774 sb = al->icap.reply->header.getByName(fmt->data.header.header);
775 out = sb.termedBuf();
776 quote = 1;
777 }
778 break;
779
780 case LFT_ICAP_REP_HEADER_ELEM:
781 if (NULL != al->icap.reply)
782 sb = al->icap.reply->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
783
784 out = sb.termedBuf();
785
786 quote = 1;
787
788 break;
789
790 case LFT_ICAP_REP_ALL_HEADERS:
791 if (al->icap.reply) {
792 HttpHeaderPos pos = HttpHeaderInitPos;
793 while (const HttpHeaderEntry *e = al->icap.reply->header.getEntry(&pos)) {
794 sb.append(e->name);
795 sb.append(": ");
796 sb.append(e->value);
797 sb.append("\r\n");
798 }
799 out = sb.termedBuf();
800 quote = 1;
801 }
802 break;
803
804 case LFT_ICAP_TR_RESPONSE_TIME:
01bd87d8
CT
805 outtv = al->icap.trTime;
806 doMsec = 1;
38e16f92
AJ
807 break;
808
809 case LFT_ICAP_IO_TIME:
01bd87d8
CT
810 outtv = al->icap.ioTime;
811 doMsec = 1;
38e16f92
AJ
812 break;
813
814 case LFT_ICAP_STATUS_CODE:
815 outint = al->icap.resStatus;
816 doint = 1;
817 break;
818
819 case LFT_ICAP_OUTCOME:
820 out = al->icap.outcome;
821 break;
822
823 case LFT_ICAP_TOTAL_TIME:
01bd87d8
CT
824 outtv = al->icap.processingTime;
825 doMsec = 1;
38e16f92
AJ
826 break;
827#endif
828 case LFT_REQUEST_HEADER_ELEM:
bd59d61c
EB
829 if (const HttpMsg *msg = actualRequestHeader(al))
830 sb = msg->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
38e16f92
AJ
831
832 out = sb.termedBuf();
833
834 quote = 1;
835
836 break;
837
838 case LFT_ADAPTED_REQUEST_HEADER_ELEM:
839 if (al->adapted_request)
840 sb = al->adapted_request->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
841
842 out = sb.termedBuf();
843
844 quote = 1;
845
846 break;
847
bd59d61c
EB
848 case LFT_REPLY_HEADER_ELEM: {
849 if (const HttpMsg *msg = actualReplyHeader(al))
850 sb = msg->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
38e16f92
AJ
851
852 out = sb.termedBuf();
853
854 quote = 1;
bd59d61c
EB
855 }
856 break;
38e16f92
AJ
857
858 case LFT_REQUEST_ALL_HEADERS:
25dadb98 859#if USE_ADAPTATION
bd59d61c
EB
860 if (al->icap.reqMethod == Adaptation::methodRespmod) {
861 // XXX: since AccessLogEntry::Headers lacks virgin response
862 // headers, do nothing for now
863 out = nullptr;
25dadb98
AR
864 } else
865#endif
866 {
bd59d61c
EB
867 out = al->headers.request;
868 }
38e16f92
AJ
869
870 quote = 1;
871
872 break;
873
874 case LFT_ADAPTED_REQUEST_ALL_HEADERS:
875 out = al->headers.adapted_request;
876
877 quote = 1;
878
879 break;
880
881 case LFT_REPLY_ALL_HEADERS:
882 out = al->headers.reply;
25dadb98 883#if USE_ADAPTATION
bd59d61c
EB
884 if (!out && al->icap.reqMethod == Adaptation::methodReqmod)
885 out = al->headers.adapted_request;
25dadb98 886#endif
38e16f92
AJ
887
888 quote = 1;
889
890 break;
891
892 case LFT_USER_NAME:
c0e8c76f
AJ
893#if USE_AUTH
894 if (al->request && al->request->auth_user_request != NULL)
895 out = strOrNull(al->request->auth_user_request->username());
896#endif
93cc83e7
AJ
897 if (!out && al->request && al->request->extacl_user.size()) {
898 if (const char *t = al->request->extacl_user.termedBuf())
899 out = t;
900 }
901
38e16f92 902 if (!out)
bd85ea1f 903 out = strOrNull(al->cache.extuser);
93cc83e7 904
cb4f4424 905#if USE_OPENSSL
38e16f92 906 if (!out)
bd85ea1f 907 out = strOrNull(al->cache.ssluser);
38e16f92 908#endif
38e16f92 909 if (!out)
bd85ea1f 910 out = strOrNull(al->cache.rfc931);
38e16f92
AJ
911 break;
912
913 case LFT_USER_LOGIN:
c0e8c76f
AJ
914#if USE_AUTH
915 if (al->request && al->request->auth_user_request != NULL)
916 out = strOrNull(al->request->auth_user_request->username());
917#endif
38e16f92
AJ
918 break;
919
920 case LFT_USER_IDENT:
bd85ea1f 921 out = strOrNull(al->cache.rfc931);
38e16f92
AJ
922 break;
923
924 case LFT_USER_EXTERNAL:
93cc83e7
AJ
925 if (al->request && al->request->extacl_user.size()) {
926 if (const char *t = al->request->extacl_user.termedBuf())
927 out = t;
928 }
4e56d7f6
AJ
929
930 if (!out)
931 out = strOrNull(al->cache.extuser);
38e16f92
AJ
932 break;
933
f53969cc
SM
934 /* case LFT_USER_REALM: */
935 /* case LFT_USER_SCHEME: */
38e16f92 936
f53969cc
SM
937 // the fmt->type can not be LFT_HTTP_SENT_STATUS_CODE_OLD_30
938 // but compiler complains if ommited
38e16f92
AJ
939 case LFT_HTTP_SENT_STATUS_CODE_OLD_30:
940 case LFT_HTTP_SENT_STATUS_CODE:
941 outint = al->http.code;
942
943 doint = 1;
944
945 break;
946
947 case LFT_HTTP_RECEIVED_STATUS_CODE:
955394ce 948 if (al->hier.peer_reply_status == Http::scNone) {
38e16f92
AJ
949 out = "-";
950 } else {
951 outint = al->hier.peer_reply_status;
952 doint = 1;
953 }
954 break;
f53969cc
SM
955 /* case LFT_HTTP_STATUS:
956 * out = statusline->text;
957 * quote = 1;
958 * break;
959 */
38e16f92
AJ
960 case LFT_HTTP_BODY_BYTES_READ:
961 if (al->hier.bodyBytesRead >= 0) {
962 outoff = al->hier.bodyBytesRead;
963 dooff = 1;
964 }
965 // else if hier.bodyBytesRead < 0 we did not have any data exchange with
966 // a peer server so just print a "-" (eg requests served from cache,
967 // or internal error messages).
968 break;
969
970 case LFT_SQUID_STATUS:
a981b360 971 out = al->cache.code.c_str();
38e16f92
AJ
972 break;
973
974 case LFT_SQUID_ERROR:
975 if (al->request && al->request->errType != ERR_NONE)
976 out = errorPageName(al->request->errType);
977 break;
978
979 case LFT_SQUID_ERROR_DETAIL:
cb4f4424 980#if USE_OPENSSL
2f3e52b5 981 if (al->request && al->request->errType == ERR_SECURE_CONNECT_FAIL) {
7598eb63
CT
982 if (! (out = Ssl::GetErrorName(al->request->errDetail)))
983 out = sslErrorName(al->request->errDetail, tmp, sizeof(tmp));
e83cdc25 984 } else
2f3e52b5 985#endif
e83cdc25 986 if (al->request && al->request->errDetail != ERR_DETAIL_NONE) {
4e56d7f6 987 if (al->request->errDetail > ERR_DETAIL_START && al->request->errDetail < ERR_DETAIL_MAX)
e83cdc25
A
988 out = errorDetailName(al->request->errDetail);
989 else {
990 if (al->request->errDetail >= ERR_DETAIL_EXCEPTION_START)
991 snprintf(tmp, sizeof(tmp), "%s=0x%X",
992 errorDetailName(al->request->errDetail), (uint32_t) al->request->errDetail);
993 else
994 snprintf(tmp, sizeof(tmp), "%s=%d",
995 errorDetailName(al->request->errDetail), al->request->errDetail);
996 out = tmp;
997 }
38e16f92 998 }
38e16f92
AJ
999 break;
1000
1001 case LFT_SQUID_HIERARCHY:
1002 if (al->hier.ping.timedout)
1003 mb.append("TIMEOUT_", 8);
1004
1005 out = hier_code_str[al->hier.code];
1006
1007 break;
1008
1009 case LFT_MIME_TYPE:
1010 out = al->http.content_type;
1011
1012 break;
1013
1014 case LFT_CLIENT_REQ_METHOD:
1015 if (al->request) {
7f06a3d8
AJ
1016 const SBuf &s = al->request->method.image();
1017 sb.append(s.rawContent(), s.length());
1018 out = sb.termedBuf();
38e16f92
AJ
1019 quote = 1;
1020 }
1021 break;
1022
1023 case LFT_CLIENT_REQ_URI:
1024 // original client URI
1025 if (al->request) {
851feda6
AJ
1026 const SBuf &s = al->request->effectiveRequestUri();
1027 sb.append(s.rawContent(), s.length());
1028 out = sb.termedBuf();
38e16f92
AJ
1029 quote = 1;
1030 }
1031 break;
1032
5aca9cf2
AJ
1033 case LFT_CLIENT_REQ_URLSCHEME:
1034 if (al->request) {
d31d59d8
AJ
1035 const SBuf s(al->request->url.getScheme().image());
1036 sb.append(s.rawContent(), s.length());
1037 out = sb.termedBuf();
5aca9cf2
AJ
1038 quote = 1;
1039 }
1040 break;
1041
fa450988
AJ
1042 case LFT_CLIENT_REQ_URLDOMAIN:
1043 if (al->request) {
5c51bffb 1044 out = al->request->url.host();
fa450988
AJ
1045 quote = 1;
1046 }
1047 break;
1048
5aca9cf2
AJ
1049 case LFT_CLIENT_REQ_URLPORT:
1050 if (al->request) {
5c51bffb 1051 outint = al->request->url.port();
5aca9cf2
AJ
1052 doint = 1;
1053 }
1054 break;
1055
38e16f92
AJ
1056 case LFT_REQUEST_URLPATH_OLD_31:
1057 case LFT_CLIENT_REQ_URLPATH:
1058 if (al->request) {
51b5dcf5
AJ
1059 SBuf s = al->request->url.path();
1060 out = s.c_str();
38e16f92
AJ
1061 quote = 1;
1062 }
1063 break;
1064
1065 case LFT_CLIENT_REQ_VERSION:
1066 if (al->request) {
1067 snprintf(tmp, sizeof(tmp), "%d.%d", (int) al->request->http_ver.major, (int) al->request->http_ver.minor);
1068 out = tmp;
1069 }
1070 break;
1071
1072 case LFT_REQUEST_METHOD:
3736fdd6
SM
1073 {
1074 const SBuf s(al->getLogMethod());
1075 sb.append(s.rawContent(), s.length());
1076 out = sb.termedBuf();
1077 quote = 1;
1078 }
1079 break;
38e16f92
AJ
1080
1081 case LFT_REQUEST_URI:
f57ae909
NH
1082 if (!al->url.isEmpty()) {
1083 const SBuf &s = al->url;
1084 sb.append(s.rawContent(), s.length());
1085 out = sb.termedBuf();
1086 }
38e16f92
AJ
1087 break;
1088
1089 case LFT_REQUEST_VERSION_OLD_2X:
1090 case LFT_REQUEST_VERSION:
1091 snprintf(tmp, sizeof(tmp), "%d.%d", (int) al->http.version.major, (int) al->http.version.minor);
1092 out = tmp;
1093 break;
1094
1095 case LFT_SERVER_REQ_METHOD:
1096 if (al->adapted_request) {
7f06a3d8
AJ
1097 const SBuf &s = al->adapted_request->method.image();
1098 sb.append(s.rawContent(), s.length());
1099 out = sb.termedBuf();
38e16f92
AJ
1100 quote = 1;
1101 }
1102 break;
1103
1104 case LFT_SERVER_REQ_URI:
1105 // adapted request URI sent to server/peer
1106 if (al->adapted_request) {
851feda6
AJ
1107 const SBuf &s = al->adapted_request->effectiveRequestUri();
1108 sb.append(s.rawContent(), s.length());
1109 out = sb.termedBuf();
38e16f92
AJ
1110 quote = 1;
1111 }
1112 break;
1113
5aca9cf2
AJ
1114 case LFT_SERVER_REQ_URLSCHEME:
1115 if (al->adapted_request) {
d31d59d8
AJ
1116 const SBuf s(al->adapted_request->url.getScheme().image());
1117 sb.append(s.rawContent(), s.length());
1118 out = sb.termedBuf();
5aca9cf2
AJ
1119 quote = 1;
1120 }
1121 break;
1122
1123 case LFT_SERVER_REQ_URLDOMAIN:
1124 if (al->adapted_request) {
5c51bffb 1125 out = al->adapted_request->url.host();
5aca9cf2
AJ
1126 quote = 1;
1127 }
1128 break;
1129
1130 case LFT_SERVER_REQ_URLPORT:
1131 if (al->adapted_request) {
5c51bffb 1132 outint = al->adapted_request->url.port();
5aca9cf2
AJ
1133 doint = 1;
1134 }
1135 break;
1136
38e16f92
AJ
1137 case LFT_SERVER_REQ_URLPATH:
1138 if (al->adapted_request) {
51b5dcf5
AJ
1139 SBuf s = al->adapted_request->url.path();
1140 out = s.c_str();
38e16f92
AJ
1141 quote = 1;
1142 }
1143 break;
1144
1145 case LFT_SERVER_REQ_VERSION:
1146 if (al->adapted_request) {
1147 snprintf(tmp, sizeof(tmp), "%d.%d",
1148 (int) al->adapted_request->http_ver.major,
1149 (int) al->adapted_request->http_ver.minor);
1150 out = tmp;
1151 }
1152 break;
1153
d6df21d2 1154 case LFT_CLIENT_REQUEST_SIZE_TOTAL:
cc0ca3b9 1155 outoff = al->http.clientRequestSz.messageTotal();
38e16f92
AJ
1156 dooff = 1;
1157 break;
1158
d6df21d2 1159 case LFT_CLIENT_REQUEST_SIZE_HEADERS:
cc0ca3b9 1160 outoff = al->http.clientRequestSz.header;
38e16f92
AJ
1161 dooff =1;
1162 break;
d6df21d2 1163
f53969cc
SM
1164 /*case LFT_REQUEST_SIZE_BODY: */
1165 /*case LFT_REQUEST_SIZE_BODY_NO_TE: */
38e16f92 1166
d6df21d2 1167 case LFT_ADAPTED_REPLY_SIZE_TOTAL:
cc0ca3b9 1168 outoff = al->http.clientReplySz.messageTotal();
38e16f92
AJ
1169 dooff = 1;
1170 break;
1171
1172 case LFT_REPLY_HIGHOFFSET:
1173 outoff = al->cache.highOffset;
1174
1175 dooff = 1;
1176
1177 break;
1178
1179 case LFT_REPLY_OBJECTSIZE:
1180 outoff = al->cache.objectSize;
1181
1182 dooff = 1;
1183
1184 break;
1185
d6df21d2 1186 case LFT_ADAPTED_REPLY_SIZE_HEADERS:
cc0ca3b9 1187 outint = al->http.clientReplySz.header;
38e16f92
AJ
1188 doint = 1;
1189 break;
d6df21d2 1190
f53969cc
SM
1191 /*case LFT_REPLY_SIZE_BODY: */
1192 /*case LFT_REPLY_SIZE_BODY_NO_TE: */
38e16f92 1193
d6df21d2 1194 case LFT_CLIENT_IO_SIZE_TOTAL:
cc0ca3b9 1195 outint = al->http.clientRequestSz.messageTotal() + al->http.clientReplySz.messageTotal();
d6df21d2
AJ
1196 doint = 1;
1197 break;
f53969cc 1198 /*case LFT_SERVER_IO_SIZE_TOTAL: */
d6df21d2 1199
38e16f92
AJ
1200 case LFT_TAG:
1201 if (al->request)
1202 out = al->request->tag.termedBuf();
1203
1204 quote = 1;
1205
1206 break;
1207
38e16f92
AJ
1208 case LFT_EXT_LOG:
1209 if (al->request)
1210 out = al->request->extacl_log.termedBuf();
1211
1212 quote = 1;
1213
1214 break;
1215
1216 case LFT_SEQUENCE_NUMBER:
1217 outoff = logSequenceNumber;
1218 dooff = 1;
1219 break;
1220
cb4f4424 1221#if USE_OPENSSL
08097970
AR
1222 case LFT_SSL_BUMP_MODE: {
1223 const Ssl::BumpMode mode = static_cast<Ssl::BumpMode>(al->ssl.bumpMode);
1224 // for Ssl::bumpEnd, Ssl::bumpMode() returns NULL and we log '-'
1225 out = Ssl::bumpMode(mode);
08097970 1226 }
3736fdd6 1227 break;
4e56d7f6
AJ
1228
1229 case LFT_EXT_ACL_USER_CERT_RAW:
1230 if (al->request) {
1231 ConnStateData *conn = al->request->clientConnectionManager.get();
33cc0629
AJ
1232 if (conn && Comm::IsConnOpen(conn->clientConnection)) {
1233 if (auto ssl = fd_table[conn->clientConnection->fd].ssl.get())
4e56d7f6
AJ
1234 out = sslGetUserCertificatePEM(ssl);
1235 }
1236 }
1237 break;
1238
1239 case LFT_EXT_ACL_USER_CERTCHAIN_RAW:
1240 if (al->request) {
1241 ConnStateData *conn = al->request->clientConnectionManager.get();
33cc0629
AJ
1242 if (conn && Comm::IsConnOpen(conn->clientConnection)) {
1243 if (auto ssl = fd_table[conn->clientConnection->fd].ssl.get())
4e56d7f6
AJ
1244 out = sslGetUserCertificatePEM(ssl);
1245 }
1246 }
1247 break;
1248
1249 case LFT_EXT_ACL_USER_CERT:
1250 if (al->request) {
1251 ConnStateData *conn = al->request->clientConnectionManager.get();
33cc0629
AJ
1252 if (conn && Comm::IsConnOpen(conn->clientConnection)) {
1253 if (auto ssl = fd_table[conn->clientConnection->fd].ssl.get())
4e56d7f6
AJ
1254 out = sslGetUserAttribute(ssl, format->data.header.header);
1255 }
1256 }
1257 break;
1258
1259 case LFT_EXT_ACL_USER_CA_CERT:
1260 if (al->request) {
1261 ConnStateData *conn = al->request->clientConnectionManager.get();
33cc0629
AJ
1262 if (conn && Comm::IsConnOpen(conn->clientConnection)) {
1263 if (auto ssl = fd_table[conn->clientConnection->fd].ssl.get())
3736fdd6 1264 out = sslGetCAAttribute(ssl, format->data.header.header);
4e56d7f6
AJ
1265 }
1266 }
1267 break;
71cae389 1268
f4698e0b
CT
1269 case LFT_SSL_USER_CERT_SUBJECT:
1270 if (X509 *cert = al->cache.sslClientCert.get()) {
1271 if (X509_NAME *subject = X509_get_subject_name(cert)) {
1272 X509_NAME_oneline(subject, tmp, sizeof(tmp));
1273 out = tmp;
1274 }
1275 }
1276 break;
1277
1278 case LFT_SSL_USER_CERT_ISSUER:
1279 if (X509 *cert = al->cache.sslClientCert.get()) {
1280 if (X509_NAME *issuer = X509_get_issuer_name(cert)) {
1281 X509_NAME_oneline(issuer, tmp, sizeof(tmp));
1282 out = tmp;
1283 }
1284 }
1285 break;
4e56d7f6 1286
cedca6e7
CT
1287 case LFT_SSL_CLIENT_SNI:
1288 if (al->request && al->request->clientConnectionManager.valid()) {
1289 if (Ssl::ServerBump * srvBump = al->request->clientConnectionManager->serverBump()) {
1290 if (!srvBump->clientSni.isEmpty())
1291 out = srvBump->clientSni.c_str();
1292 }
1293 }
1294 break;
789dda8d 1295
7598eb63
CT
1296 case LFT_SSL_SERVER_CERT_ERRORS:
1297 if (al->request && al->request->clientConnectionManager.valid()) {
1298 if (Ssl::ServerBump * srvBump = al->request->clientConnectionManager->serverBump()) {
1299 const char *separator = fmt->data.string ? fmt->data.string : ":";
92e3827b 1300 for (const Security::CertErrors *sslError = srvBump->sslErrors(); sslError != nullptr; sslError = sslError->next) {
7598eb63
CT
1301 if (sb.size())
1302 sb.append(separator);
1303 if (const char *errorName = Ssl::GetErrorName(sslError->element.code))
1304 sb.append(errorName);
1305 else
1306 sb.append(sslErrorName(sslError->element.code, tmp, sizeof(tmp)));
b4e6a8d4
CT
1307 if (sslError->element.depth >= 0) {
1308 snprintf(tmp, sizeof(tmp), "@depth=%d", sslError->element.depth);
1309 sb.append(tmp);
1310 }
7598eb63
CT
1311 }
1312 if (sb.size())
1313 out = sb.termedBuf();
1314 }
1315 }
cedca6e7 1316 break;
789dda8d
CT
1317
1318 case LFT_SSL_SERVER_CERT_ISSUER:
1319 case LFT_SSL_SERVER_CERT_SUBJECT:
d4ddb3e6
CT
1320 if (al->request && al->request->clientConnectionManager.valid()) {
1321 if (Ssl::ServerBump * srvBump = al->request->clientConnectionManager->serverBump()) {
1322 if (X509 *serverCert = srvBump->serverCert.get()) {
1323 if (fmt->type == LFT_SSL_SERVER_CERT_SUBJECT)
1324 out = Ssl::GetX509UserAttribute(serverCert, "DN");
1325 else
1326 out = Ssl::GetX509CAAttribute(serverCert, "DN");
1327 }
1328 }
1329 }
789dda8d 1330 break;
2bcab852
CT
1331
1332 case LFT_TLS_CLIENT_NEGOTIATED_VERSION:
1333 if (al->tcpClient != nullptr && al->tcpClient->hasTlsNegotiations())
1334 out = al->tcpClient->hasTlsNegotiations()->negotiatedVersion();
1335 break;
1336
1337 case LFT_TLS_SERVER_NEGOTIATED_VERSION:
1338 if (al->hier.tcpServer != nullptr && al->hier.tcpServer->hasTlsNegotiations())
1339 out = al->hier.tcpServer->hasTlsNegotiations()->negotiatedVersion();
1340 break;
1341
1342 case LFT_TLS_CLIENT_RECEIVED_HELLO_VERSION:
1343 if (al->tcpClient != nullptr && al->tcpClient->hasTlsNegotiations())
1344 out = al->tcpClient->hasTlsNegotiations()->helloVersion();
1345 break;
1346
1347 case LFT_TLS_SERVER_RECEIVED_HELLO_VERSION:
1348 if (al->hier.tcpServer != nullptr && al->hier.tcpServer->hasTlsNegotiations())
1349 out = al->hier.tcpServer->hasTlsNegotiations()->helloVersion();
1350 break;
1351
1352 case LFT_TLS_CLIENT_SUPPORTED_VERSION:
1353 if (al->tcpClient != nullptr && al->tcpClient->hasTlsNegotiations())
1354 out = al->tcpClient->hasTlsNegotiations()->supportedVersion();
1355 break;
1356
1357 case LFT_TLS_SERVER_SUPPORTED_VERSION:
1358 if (al->hier.tcpServer != nullptr && al->hier.tcpServer->hasTlsNegotiations())
1359 out = al->hier.tcpServer->hasTlsNegotiations()->supportedVersion();
1360 break;
1361
1362 case LFT_TLS_CLIENT_NEGOTIATED_CIPHER:
1363 if (al->tcpClient != nullptr && al->tcpClient->hasTlsNegotiations())
1364 out = al->tcpClient->hasTlsNegotiations()->cipherName();
1365 break;
1366
1367 case LFT_TLS_SERVER_NEGOTIATED_CIPHER:
1368 if (al->hier.tcpServer != nullptr && al->hier.tcpServer->hasTlsNegotiations())
1369 out = al->hier.tcpServer->hasTlsNegotiations()->cipherName();
1370 break;
08097970 1371#endif
f123f5e9 1372
d074f918
TT
1373 case LFT_REQUEST_URLGROUP_OLD_2X:
1374 assert(LFT_REQUEST_URLGROUP_OLD_2X == 0); // should never happen.
1375
d7f4a0b7 1376 case LFT_NOTE:
c7bcf010
CT
1377 tmp[0] = fmt->data.header.separator;
1378 tmp[1] = '\0';
1379 if (fmt->data.header.header && *fmt->data.header.header) {
1380 const char *separator = tmp;
cf9f0261 1381#if USE_ADAPTATION
7f0ceafc 1382 Adaptation::History::Pointer ah = al->request ? al->request->adaptHistory() : Adaptation::History::Pointer();
cf9f0261 1383 if (ah != NULL && ah->metaHeaders != NULL) {
c7bcf010 1384 if (const char *meta = ah->metaHeaders->find(fmt->data.header.header, separator))
cf9f0261
CT
1385 sb.append(meta);
1386 }
1387#endif
f4f55a21 1388 if (al->notes != NULL) {
c7bcf010 1389 if (const char *note = al->notes->find(fmt->data.header.header, separator)) {
cf9f0261 1390 if (sb.size())
c7bcf010 1391 sb.append(separator);
cf9f0261
CT
1392 sb.append(note);
1393 }
1394 }
d7f4a0b7
CT
1395 out = sb.termedBuf();
1396 quote = 1;
1397 } else {
c7bcf010
CT
1398 // if no argument given use default "\r\n" as notes separator
1399 const char *separator = fmt->data.string ? tmp : "\r\n";
cf9f0261 1400#if USE_ADAPTATION
7f0ceafc 1401 Adaptation::History::Pointer ah = al->request ? al->request->adaptHistory() : Adaptation::History::Pointer();
cf9f0261 1402 if (ah != NULL && ah->metaHeaders != NULL && !ah->metaHeaders->empty())
c7bcf010 1403 sb.append(ah->metaHeaders->toString(separator));
cf9f0261 1404#endif
f4f55a21 1405 if (al->notes != NULL && !al->notes->empty())
c7bcf010 1406 sb.append(al->notes->toString(separator));
f4f55a21 1407
d7f4a0b7
CT
1408 out = sb.termedBuf();
1409 quote = 1;
1410 }
1411 break;
08097970 1412
d4806c91
CT
1413 case LFT_CREDENTIALS:
1414#if USE_AUTH
1415 if (al->request && al->request->auth_user_request != NULL)
1416 out = strOrNull(al->request->auth_user_request->credentialsStr());
1417#endif
1418
1419 break;
1420
38e16f92
AJ
1421 case LFT_PERCENT:
1422 out = "%";
5aca9cf2 1423 break;
38e16f92 1424
5aca9cf2 1425 case LFT_EXT_ACL_NAME:
4ff6370b 1426 out = al->lastAclName;
4e56d7f6
AJ
1427 break;
1428
5aca9cf2 1429 case LFT_EXT_ACL_DATA:
b0e14ce2
NH
1430 if (!al->lastAclData.isEmpty())
1431 out = al->lastAclData.c_str();
38e16f92
AJ
1432 break;
1433 }
1434
1435 if (dooff) {
8846a2b4 1436 snprintf(tmp, sizeof(tmp), "%0*" PRId64, fmt->zero && fmt->widthMin >= 0 ? fmt->widthMin : 0, outoff);
38e16f92
AJ
1437 out = tmp;
1438
1439 } else if (doint) {
8846a2b4 1440 snprintf(tmp, sizeof(tmp), "%0*ld", fmt->zero && fmt->widthMin >= 0 ? fmt->widthMin : 0, outint);
38e16f92 1441 out = tmp;
01bd87d8
CT
1442 } else if (doMsec) {
1443 if (fmt->widthMax < 0) {
1444 snprintf(tmp, sizeof(tmp), "%0*ld", fmt->widthMin , tvToMsec(outtv));
1445 } else {
1446 int precision = fmt->widthMax;
1447 snprintf(tmp, sizeof(tmp), "%0*" PRId64 ".%0*" PRId64 "", fmt->zero && (fmt->widthMin - precision - 1 >= 0) ? fmt->widthMin - precision - 1 : 0, static_cast<int64_t>(outtv.tv_sec * 1000 + outtv.tv_usec / 1000), precision, static_cast<int64_t>((outtv.tv_usec % 1000 )* (1000 / fmt->divisor)));
1448 }
1449 out = tmp;
1450 } else if (doSec) {
1451 int precision = fmt->widthMax >=0 ? fmt->widthMax :3;
1452 snprintf(tmp, sizeof(tmp), "%0*" PRId64 ".%0*d", fmt->zero && (fmt->widthMin - precision - 1 >= 0) ? fmt->widthMin - precision - 1 : 0, static_cast<int64_t>(outtv.tv_sec), precision, (int)(outtv.tv_usec / fmt->divisor));
1453 out = tmp;
38e16f92
AJ
1454 }
1455
1456 if (out && *out) {
1457 if (quote || fmt->quote != LOG_QUOTE_NONE) {
1458 char *newout = NULL;
1459 int newfree = 0;
1460
1461 switch (fmt->quote) {
1462
1463 case LOG_QUOTE_NONE:
1464 newout = rfc1738_escape_unescaped(out);
1465 break;
1466
1467 case LOG_QUOTE_QUOTES: {
1468 size_t out_len = static_cast<size_t>(strlen(out)) * 2 + 1;
1469 if (out_len >= sizeof(tmp)) {
1470 newout = (char *)xmalloc(out_len);
1471 newfree = 1;
1472 } else
1473 newout = tmp;
1474 log_quoted_string(out, newout);
1475 }
1476 break;
1477
1478 case LOG_QUOTE_MIMEBLOB:
1479 newout = QuoteMimeBlob(out);
1480 newfree = 1;
1481 break;
1482
1483 case LOG_QUOTE_URL:
1484 newout = rfc1738_escape(out);
1485 break;
1486
95d78f10
AJ
1487 case LOG_QUOTE_SHELL: {
1488 MemBuf mbq;
1489 mbq.init();
1490 strwordquote(&mbq, out);
1491 newout = mbq.content();
1492 mbq.stolen = 1;
1493 newfree = 1;
3736fdd6
SM
1494 }
1495 break;
95d78f10 1496
38e16f92
AJ
1497 case LOG_QUOTE_RAW:
1498 break;
1499 }
1500
1501 if (newout) {
1502 if (dofree)
1503 safe_free(out);
1504
1505 out = newout;
1506
1507 dofree = newfree;
1508 }
1509 }
1510
c32c6db7 1511 // enforce width limits if configured
01bd87d8 1512 const bool haveMaxWidth = fmt->widthMax >=0 && !doint && !dooff && !doMsec && !doSec;
8846a2b4
CT
1513 if (haveMaxWidth || fmt->widthMin) {
1514 const int minWidth = fmt->widthMin >= 0 ?
b8ad91f5 1515 fmt->widthMin :0;
c32c6db7 1516 const int maxWidth = haveMaxWidth ?
8846a2b4 1517 fmt->widthMax : strlen(out);
c32c6db7 1518
38e16f92 1519 if (fmt->left)
4391cd15 1520 mb.appendf("%-*.*s", minWidth, maxWidth, out);
38e16f92 1521 else
4391cd15 1522 mb.appendf("%*.*s", minWidth, maxWidth, out);
38e16f92
AJ
1523 } else
1524 mb.append(out, strlen(out));
1525 } else {
1526 mb.append("-", 1);
1527 }
1528
1529 if (fmt->space)
1530 mb.append(" ", 1);
1531
1532 sb.clean();
1533
1534 if (dofree)
1535 safe_free(out);
1536 }
1537}
f53969cc 1538