#include "format/Quoting.h"
#include "format/Token.h"
#include "fqdncache.h"
+#include "http/Stream.h"
#include "HttpRequest.h"
#include "MemBuf.h"
#include "rfc1738.h"
+#include "security/CertError.h"
#include "security/NegotiationHistory.h"
#include "SquidTime.h"
#include "Store.h"
/// Convert a string to NULL pointer if it is ""
#define strOrNull(s) ((s)==NULL||(s)[0]=='\0'?NULL:(s))
+const SBuf Format::Dash("-");
+
Format::Format::Format(const char *n) :
format(NULL),
next(NULL)
#if USE_OPENSSL
static char *
-sslErrorName(Ssl::ssl_error_t err, char *buf, size_t size)
+sslErrorName(Security::ErrorCode err, char *buf, size_t size)
{
snprintf(buf, size, "SSL_ERR=%d", err);
return buf;
}
#endif
+static const HttpMsg *
+actualReplyHeader(const AccessLogEntry::Pointer &al)
+{
+ const HttpMsg *msg = al->reply;
+ if (!msg && al->icap.reqMethod == Adaptation::methodReqmod)
+ msg = al->adapted_request;
+ return msg;
+}
+
+static const HttpMsg *
+actualRequestHeader(const AccessLogEntry::Pointer &al)
+{
+ if (al->icap.reqMethod == Adaptation::methodRespmod) {
+ // XXX: for now AccessLogEntry lacks virgin response headers
+ return nullptr;
+ }
+ return al->request;
+}
+
void
Format::Format::assemble(MemBuf &mb, const AccessLogEntry::Pointer &al, int logSequenceNumber) const
{
break;
case LFT_REQUEST_HEADER:
-
- if (al->request)
- sb = al->request->header.getByName(fmt->data.header.header);
+ if (const HttpMsg *msg = actualRequestHeader(al))
+ sb = msg->header.getByName(fmt->data.header.header);
out = sb.termedBuf();
break;
- case LFT_REPLY_HEADER:
- if (al->reply)
- sb = al->reply->header.getByName(fmt->data.header.header);
+ case LFT_REPLY_HEADER: {
+ if (const HttpMsg *msg = actualReplyHeader(al))
+ sb = msg->header.getByName(fmt->data.header.header);
out = sb.termedBuf();
quote = 1;
-
- break;
+ }
+ break;
#if USE_ADAPTATION
case LFT_ADAPTATION_SUM_XACT_TIMES:
break;
#endif
case LFT_REQUEST_HEADER_ELEM:
- if (al->request)
- sb = al->request->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
+ if (const HttpMsg *msg = actualRequestHeader(al))
+ sb = msg->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
out = sb.termedBuf();
break;
- case LFT_REPLY_HEADER_ELEM:
- if (al->reply)
- sb = al->reply->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
+ case LFT_REPLY_HEADER_ELEM: {
+ if (const HttpMsg *msg = actualReplyHeader(al))
+ sb = msg->header.getByNameListMember(fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
out = sb.termedBuf();
quote = 1;
-
- break;
+ }
+ break;
case LFT_REQUEST_ALL_HEADERS:
- out = al->headers.request;
+ if (al->icap.reqMethod == Adaptation::methodRespmod) {
+ // XXX: since AccessLogEntry::Headers lacks virgin response
+ // headers, do nothing for now
+ out = nullptr;
+ } else {
+ out = al->headers.request;
+ }
quote = 1;
case LFT_REPLY_ALL_HEADERS:
out = al->headers.reply;
+ if (!out && al->icap.reqMethod == Adaptation::methodReqmod)
+ out = al->headers.adapted_request;
quote = 1;
if (al->request && al->request->auth_user_request != NULL)
out = strOrNull(al->request->auth_user_request->username());
#endif
+ if (!out && al->request && al->request->extacl_user.size()) {
+ if (const char *t = al->request->extacl_user.termedBuf())
+ out = t;
+ }
+
if (!out)
out = strOrNull(al->cache.extuser);
+
#if USE_OPENSSL
if (!out)
out = strOrNull(al->cache.ssluser);
break;
case LFT_USER_EXTERNAL:
- if (al->request && al->request->extacl_user.size())
- out = al->request->extacl_user.termedBuf();
+ if (al->request && al->request->extacl_user.size()) {
+ if (const char *t = al->request->extacl_user.termedBuf())
+ out = t;
+ }
if (!out)
out = strOrNull(al->cache.extuser);
case LFT_CLIENT_REQ_URLSCHEME:
if (al->request) {
- out = al->request->url.getScheme().c_str();
+ const SBuf s(al->request->url.getScheme().image());
+ sb.append(s.rawContent(), s.length());
+ out = sb.termedBuf();
quote = 1;
}
break;
break;
case LFT_REQUEST_URI:
- out = al->url;
+ if (!al->url.isEmpty()) {
+ const SBuf &s = al->url;
+ sb.append(s.rawContent(), s.length());
+ out = sb.termedBuf();
+ }
break;
case LFT_REQUEST_VERSION_OLD_2X:
case LFT_SERVER_REQ_URLSCHEME:
if (al->adapted_request) {
- out = al->adapted_request->url.getScheme().c_str();
+ const SBuf s(al->adapted_request->url.getScheme().image());
+ sb.append(s.rawContent(), s.length());
+ out = sb.termedBuf();
quote = 1;
}
break;
case LFT_EXT_ACL_USER_CERT_RAW:
if (al->request) {
ConnStateData *conn = al->request->clientConnectionManager.get();
- if (conn != NULL && Comm::IsConnOpen(conn->clientConnection)) {
- if (SSL *ssl = fd_table[conn->clientConnection->fd].ssl)
+ if (conn && Comm::IsConnOpen(conn->clientConnection)) {
+ if (auto ssl = fd_table[conn->clientConnection->fd].ssl.get())
out = sslGetUserCertificatePEM(ssl);
}
}
case LFT_EXT_ACL_USER_CERTCHAIN_RAW:
if (al->request) {
ConnStateData *conn = al->request->clientConnectionManager.get();
- if (conn != NULL && Comm::IsConnOpen(conn->clientConnection)) {
- if (SSL *ssl = fd_table[conn->clientConnection->fd].ssl)
+ if (conn && Comm::IsConnOpen(conn->clientConnection)) {
+ if (auto ssl = fd_table[conn->clientConnection->fd].ssl.get())
out = sslGetUserCertificatePEM(ssl);
}
}
case LFT_EXT_ACL_USER_CERT:
if (al->request) {
ConnStateData *conn = al->request->clientConnectionManager.get();
- if (conn != NULL && Comm::IsConnOpen(conn->clientConnection)) {
- if (SSL *ssl = fd_table[conn->clientConnection->fd].ssl)
+ if (conn && Comm::IsConnOpen(conn->clientConnection)) {
+ if (auto ssl = fd_table[conn->clientConnection->fd].ssl.get())
out = sslGetUserAttribute(ssl, format->data.header.header);
}
}
case LFT_EXT_ACL_USER_CA_CERT:
if (al->request) {
ConnStateData *conn = al->request->clientConnectionManager.get();
- if (conn != NULL && Comm::IsConnOpen(conn->clientConnection)) {
- if (SSL *ssl = fd_table[conn->clientConnection->fd].ssl)
+ if (conn && Comm::IsConnOpen(conn->clientConnection)) {
+ if (auto ssl = fd_table[conn->clientConnection->fd].ssl.get())
out = sslGetCAAttribute(ssl, format->data.header.header);
}
}
if (al->request && al->request->clientConnectionManager.valid()) {
if (Ssl::ServerBump * srvBump = al->request->clientConnectionManager->serverBump()) {
const char *separator = fmt->data.string ? fmt->data.string : ":";
- for (Ssl::CertErrors *sslError = srvBump->sslErrors; sslError != NULL; sslError = sslError->next) {
+ for (const Security::CertErrors *sslError = srvBump->sslErrors(); sslError != nullptr; sslError = sslError->next) {
if (sb.size())
sb.append(separator);
if (const char *errorName = Ssl::GetErrorName(sslError->element.code))
case LFT_SSL_SERVER_CERT_ISSUER:
case LFT_SSL_SERVER_CERT_SUBJECT:
- // Not implemented
+ if (al->request && al->request->clientConnectionManager.valid()) {
+ if (Ssl::ServerBump * srvBump = al->request->clientConnectionManager->serverBump()) {
+ if (X509 *serverCert = srvBump->serverCert.get()) {
+ if (fmt->type == LFT_SSL_SERVER_CERT_SUBJECT)
+ out = Ssl::GetX509UserAttribute(serverCert, "DN");
+ else
+ out = Ssl::GetX509CAAttribute(serverCert, "DN");
+ }
+ }
+ }
break;
case LFT_TLS_CLIENT_NEGOTIATED_VERSION:
break;
case LFT_EXT_ACL_DATA:
- out = al->lastAclData;
+ if (!al->lastAclData.isEmpty())
+ out = al->lastAclData.c_str();
break;
}