not available. Consider encoding the logged
value because Issuer often has spaces.
+ ssl::<cert
+ The received server x509 certificate in PEM
+ format, including BEGIN and END lines (or a
+ dash ('-') if the certificate is unavailable).
+
+ WARNING: Large certificates will exceed the
+ current 8KB access.log record limit, resulting
+ in truncated records. Such truncation usually
+ happens in the middle of a record field. The
+ limit applies to all access logging modules.
+
+ The logged certificate may have failed
+ validation and may not be trusted by Squid.
+ This field does not include any intermediate
+ certificates that may have been received from
+ the server or fetched during certificate
+ validation process.
+
+ Currently, Squid only collects server
+ certificates during step3 of SslBump
+ processing; connections that were not subject
+ to ssl_bump rules or that did not match a peek
+ or stare rule at step2 will not have the
+ server certificate information.
+
+ This field is using pass-through URL encoding
+ by default.
+
ssl::<cert_errors
The list of certificate validation errors
detected by Squid (including OpenSSL and
LFT_SSL_SERVER_CERT_SUBJECT,
LFT_SSL_SERVER_CERT_ISSUER,
LFT_SSL_SERVER_CERT_ERRORS,
+ LFT_SSL_SERVER_CERT_WHOLE,
LFT_TLS_CLIENT_NEGOTIATED_VERSION,
LFT_TLS_SERVER_NEGOTIATED_VERSION,
LFT_TLS_CLIENT_NEGOTIATED_CIPHER,
if (al->request) {
ConnStateData *conn = al->request->clientConnectionManager.get();
if (conn && Comm::IsConnOpen(conn->clientConnection)) {
- if (auto ssl = fd_table[conn->clientConnection->fd].ssl.get())
- out = sslGetUserCertificatePEM(ssl);
+ if (const auto ssl = fd_table[conn->clientConnection->fd].ssl.get()) {
+ sb = sslGetUserCertificatePEM(ssl);
+ out = sb.c_str();
+ }
}
}
break;
if (al->request) {
ConnStateData *conn = al->request->clientConnectionManager.get();
if (conn && Comm::IsConnOpen(conn->clientConnection)) {
- if (auto ssl = fd_table[conn->clientConnection->fd].ssl.get())
- out = sslGetUserCertificatePEM(ssl);
+ if (const auto ssl = fd_table[conn->clientConnection->fd].ssl.get()) {
+ sb = sslGetUserCertificatePEM(ssl);
+ out = sb.c_str();
+ }
}
}
break;
case LFT_SSL_SERVER_CERT_ISSUER:
case LFT_SSL_SERVER_CERT_SUBJECT:
+ case LFT_SSL_SERVER_CERT_WHOLE:
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
+ else if (fmt->type == LFT_SSL_SERVER_CERT_ISSUER)
out = Ssl::GetX509CAAttribute(serverCert, "DN");
+ else {
+ assert(fmt->type == LFT_SSL_SERVER_CERT_WHOLE);
+ sb = Ssl::GetX509PEM(serverCert);
+ out = sb.c_str();
+ quote = 1;
+ }
}
}
}
TokenTableEntry("<cert_subject", LFT_SSL_SERVER_CERT_SUBJECT),
TokenTableEntry("<cert_issuer", LFT_SSL_SERVER_CERT_ISSUER),
TokenTableEntry("<cert_errors", LFT_SSL_SERVER_CERT_ERRORS),
+ TokenTableEntry("<cert", LFT_SSL_SERVER_CERT_WHOLE),
TokenTableEntry(">negotiated_version", LFT_TLS_CLIENT_NEGOTIATED_VERSION),
TokenTableEntry("<negotiated_version", LFT_TLS_SERVER_NEGOTIATED_VERSION),
TokenTableEntry(">negotiated_cipher", LFT_TLS_CLIENT_NEGOTIATED_CIPHER),
return buf;
}
+SBuf
+Ssl::GetX509PEM(X509 * cert)
+{
+ assert(cert);
+
+ Ssl::BIO_Pointer bio(BIO_new(BIO_s_mem()));
+ PEM_write_bio_X509(bio.get(), cert);
+
+ char *ptr;
+ const auto len = BIO_get_mem_data(bio.get(), &ptr);
+ return SBuf(ptr, len);
+}
+
/// \ingroup ServerProtocolSSLInternal
const char *
Ssl::GetX509CAAttribute(X509 * cert, const char *attribute_name)
return sslGetUserAttribute(ssl, "emailAddress");
}
-const char *
+SBuf
sslGetUserCertificatePEM(SSL *ssl)
{
- X509 *cert;
- BIO *mem;
- static char *str = NULL;
- char *ptr;
- long len;
-
- safe_free(str);
-
- if (!ssl)
- return NULL;
-
- cert = SSL_get_peer_certificate(ssl);
-
- if (!cert)
- return NULL;
-
- mem = BIO_new(BIO_s_mem());
+ assert(ssl);
- PEM_write_bio_X509(mem, cert);
+ if (const auto cert = SSL_get_peer_certificate(ssl))
+ return Ssl::GetX509PEM(cert);
- len = BIO_get_mem_data(mem, &ptr);
-
- str = (char *)xmalloc(len + 1);
-
- memcpy(str, ptr, len);
-
- str[len] = '\0';
-
- X509_free(cert);
-
- BIO_free(mem);
-
- return str;
+ return SBuf();
}
-const char *
+SBuf
sslGetUserCertificateChainPEM(SSL *ssl)
{
- STACK_OF(X509) *chain;
- BIO *mem;
- static char *str = NULL;
- char *ptr;
- long len;
- int i;
+ assert(ssl);
- safe_free(str);
-
- if (!ssl)
- return NULL;
-
- chain = SSL_get_peer_cert_chain(ssl);
+ auto chain = SSL_get_peer_cert_chain(ssl);
if (!chain)
return sslGetUserCertificatePEM(ssl);
- mem = BIO_new(BIO_s_mem());
+ Ssl::BIO_Pointer bio(BIO_new(BIO_s_mem()));
- for (i = 0; i < sk_X509_num(chain); ++i) {
+ for (int i = 0; i < sk_X509_num(chain); ++i) {
X509 *cert = sk_X509_value(chain, i);
- PEM_write_bio_X509(mem, cert);
+ PEM_write_bio_X509(bio.get(), cert);
}
- len = BIO_get_mem_data(mem, &ptr);
-
- str = (char *)xmalloc(len + 1);
- memcpy(str, ptr, len);
- str[len] = '\0';
-
- BIO_free(mem);
-
- return str;
+ char *ptr;
+ const auto len = BIO_get_mem_data(bio.get(), &ptr);
+ return SBuf(ptr, len);
}
/// Create SSL context and apply ssl certificate and private key to it.
const char *sslGetCAAttribute(SSL *ssl, const char *attribute_name);
/// \ingroup ServerProtocolSSLAPI
-const char *sslGetUserCertificatePEM(SSL *ssl);
+SBuf sslGetUserCertificatePEM(SSL *ssl);
/// \ingroup ServerProtocolSSLAPI
-const char *sslGetUserCertificateChainPEM(SSL *ssl);
+SBuf sslGetUserCertificateChainPEM(SSL *ssl);
namespace Ssl
{
/// \ingroup ServerProtocolSSLAPI
typedef char const *GETX509ATTRIBUTE(X509 *, const char *);
+typedef SBuf GETX509PEM(X509 *);
/// \ingroup ServerProtocolSSLAPI
GETX509ATTRIBUTE GetX509UserAttribute;
/// \ingroup ServerProtocolSSLAPI
GETX509ATTRIBUTE GetX509CAAttribute;
+/// \ingroup ServerProtocolSSLAPI
+GETX509PEM GetX509PEM;
+
/// \ingroup ServerProtocolSSLAPI
GETX509ATTRIBUTE GetX509Fingerprint;
#if USE_OPENSSL
#include "fatal.h"
+#include "sbuf/SBuf.h"
/* Stub File for the ssl/libsslsquid.la convenience library */
const char *sslGetUserEmail(SSL *ssl) STUB_RETVAL(NULL)
const char *sslGetUserAttribute(SSL *ssl, const char *attribute_name) STUB_RETVAL(NULL)
const char *sslGetCAAttribute(SSL *ssl, const char *attribute_name) STUB_RETVAL(NULL)
-const char *sslGetUserCertificatePEM(SSL *ssl) STUB_RETVAL(NULL)
-const char *sslGetUserCertificateChainPEM(SSL *ssl) STUB_RETVAL(NULL)
+SBuf sslGetUserCertificatePEM(SSL *ssl) STUB_RETVAL(SBuf())
+SBuf sslGetUserCertificateChainPEM(SSL *ssl) STUB_RETVAL(SBuf())
namespace Ssl
{
//GETX509ATTRIBUTE GetX509UserAttribute;
bool checkX509ServerValidity(X509 *cert, const char *server) STUB_RETVAL(false)
int asn1timeToString(ASN1_TIME *tm, char *buf, int len) STUB_RETVAL(0)
void setClientSNI(SSL *ssl, const char *fqdn) STUB
+SBuf GetX509PEM(SSL *ssl) STUB_RETVAL(SBuf())
} //namespace Ssl
#endif
# %ssl::>sni
# %ssl::<cert_subject
# %ssl::<cert_issuer
+# %ssl::<cert