summaryrefslogtreecommitdiffstats
path: root/modules/ssl/ssl_engine_vars.c
diff options
context:
space:
mode:
Diffstat (limited to 'modules/ssl/ssl_engine_vars.c')
-rw-r--r--modules/ssl/ssl_engine_vars.c60
1 files changed, 60 insertions, 0 deletions
diff --git a/modules/ssl/ssl_engine_vars.c b/modules/ssl/ssl_engine_vars.c
index 7d09846c27..45a5a5bab6 100644
--- a/modules/ssl/ssl_engine_vars.c
+++ b/modules/ssl/ssl_engine_vars.c
@@ -52,6 +52,7 @@ static const char *ssl_var_lookup_ssl_cert_verify(apr_pool_t *p, const SSLConnRe
static const char *ssl_var_lookup_ssl_cipher(apr_pool_t *p, const SSLConnRec *sslconn, const char *var);
static void ssl_var_lookup_ssl_cipher_bits(SSL *ssl, int *usekeysize, int *algkeysize);
static const char *ssl_var_lookup_ssl_handshake_rtt(apr_pool_t *p, SSL *ssl);
+static const char *ssl_var_lookup_ssl_clienthello(apr_pool_t *p, const SSLConnRec *sslconn, const char *var);
static const char *ssl_var_lookup_ssl_version(const char *var);
static const char *ssl_var_lookup_ssl_compress_meth(SSL *ssl);
@@ -476,6 +477,9 @@ static const char *ssl_var_lookup_ssl(apr_pool_t *p, const SSLConnRec *sslconn,
else if (ssl != NULL && strcEQ(var, "HANDSHAKE_RTT")) {
result = ssl_var_lookup_ssl_handshake_rtt(p, ssl);
}
+ else if (ssl != NULL && strlen(var) >= 12 && strcEQn(var, "CLIENTHELLO_", 12)) {
+ result = ssl_var_lookup_ssl_clienthello(p, sslconn, var+12);
+ }
else if (ssl != NULL && strlen(var) > 18 && strcEQn(var, "CLIENT_CERT_CHAIN_", 18)) {
sk = SSL_get_peer_cert_chain(ssl);
result = ssl_var_lookup_ssl_cert_chain(p, sk, var+18, 1);
@@ -975,6 +979,62 @@ static const char *ssl_var_lookup_ssl_handshake_rtt(apr_pool_t *p, SSL *ssl)
return NULL;
}
+static const char *ssl_var_lookup_ssl_clienthello(apr_pool_t *p, const SSLConnRec *sslconn, const char *var)
+{
+#if OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined(LIBRESSL_VERSION_NUMBER)
+ char *value;
+ modssl_clienthello_vars *clienthello_vars;
+ apr_size_t i;
+
+ clienthello_vars = sslconn->clienthello_vars;
+
+ if (!clienthello_vars)
+ return NULL;
+
+ if (strEQ(var, "VERSION")) {
+ return apr_psprintf(p, "%04x", (uint16_t) clienthello_vars->version);
+ }
+ else if (strEQ(var, "CIPHERS") && (clienthello_vars->ciphers_len > 0)) {
+ value = apr_palloc(p, clienthello_vars->ciphers_len * 2 + 1);
+ ap_bin2hex(clienthello_vars->ciphers_data, clienthello_vars->ciphers_len, value);
+ return value;
+ }
+ else if (strEQ(var, "EXTENSIONS") && (clienthello_vars->extids_len > 0)) {
+ value = apr_palloc(p, clienthello_vars->extids_len * 4 + 1);
+ for (i = 0; i < clienthello_vars->extids_len; i++) {
+ apr_snprintf(value + i * 4, 5, "%04x", (uint16_t) clienthello_vars->extids_data[i]);
+ }
+ return value;
+ }
+ else if (strEQ(var, "GROUPS") && (clienthello_vars->ecgroups_len > 2)) {
+ value = apr_palloc(p, clienthello_vars->ecgroups_len * 2 + 1 - 2);
+ ap_bin2hex(clienthello_vars->ecgroups_data + 2, clienthello_vars->ecgroups_len - 2, value);
+ return value;
+ }
+ else if (strEQ(var, "EC_FORMATS") && (clienthello_vars->ecformats_len > 1)) {
+ value = apr_palloc(p, clienthello_vars->ecformats_len * 2 + 1 - 1);
+ ap_bin2hex(clienthello_vars->ecformats_data + 1, clienthello_vars->ecformats_len - 1, value);
+ return value;
+ }
+ else if (strEQ(var, "SIG_ALGOS") && (clienthello_vars->sigalgos_len > 2)) {
+ value = apr_palloc(p, clienthello_vars->sigalgos_len * 2 + 1 - 2);
+ ap_bin2hex(clienthello_vars->sigalgos_data + 2, clienthello_vars->sigalgos_len - 2, value);
+ return value;
+ }
+ else if (strEQ(var, "ALPN") && (clienthello_vars->alpn_len > 2)) {
+ value = apr_palloc(p, clienthello_vars->alpn_len * 2 + 1 - 2);
+ ap_bin2hex(clienthello_vars->alpn_data + 2, clienthello_vars->alpn_len - 2, value);
+ return value;
+ }
+ else if (strEQ(var, "VERSIONS") && (clienthello_vars->versions_len > 1)) {
+ value = apr_palloc(p, clienthello_vars->versions_len * 2 + 1 - 1);
+ ap_bin2hex(clienthello_vars->versions_data + 1, clienthello_vars->versions_len - 1, value);
+ return value;
+ }
+#endif
+ return NULL;
+}
+
static const char *ssl_var_lookup_ssl_version(const char *var)
{
if (strEQ(var, "INTERFACE")) {