nghttpx: Add tls_client_fingerprint_sha1 to mruby and accesslog

Also tls_client_fingerprint is renamed to
tls_client_fingerprint_sha256.
This commit is contained in:
Tatsuhiro Tsujikawa 2017-10-31 21:41:40 +09:00
parent 7008afd40e
commit 539e27812b
7 changed files with 57 additions and 23 deletions

View File

@ -368,10 +368,14 @@ respectively.
Return the TLS SNI value which client sent in this connection.
.. rb:attr_reader:: tls_client_fingerprint
.. rb:attr_reader:: tls_client_fingerprint_sha256
Return the SHA-256 fingerprint of a client certificate.
.. rb:attr_reader:: tls_client_fingerprint_sha1
Return the SHA-1 fingerprint of a client certificate.
.. rb:attr_reader:: tls_client_subject_name
Return the subject name of a client certificate.

View File

@ -191,7 +191,8 @@ LOGVARS = [
"tls_session_id",
"tls_session_reused",
"tls_sni",
"tls_client_fingerprint",
"tls_client_fingerprint_sha256",
"tls_client_fingerprint_sha1",
"tls_client_subject_name",
"backend_host",
"backend_port",

View File

@ -2482,8 +2482,10 @@ Logging:
the response. For HTTP/1, ALPN is always http/1.1,
regardless of minor version.
* $tls_cipher: cipher used for SSL/TLS connection.
* $tls_client_fingerprint: SHA-256 fingerprint of client
certificate.
* $tls_client_fingerprint_sha256: SHA-256 fingerprint of
client certificate.
* $tls_client_fingerprint_sha1: SHA-1 fingerprint of
client certificate.
* $tls_client_subject_name: subject name in client
certificate.
* $tls_protocol: protocol for SSL/TLS connection.

View File

@ -510,15 +510,6 @@ LogFragmentType log_var_lookup_token(const char *name, size_t namelen) {
break;
}
break;
case 22:
switch (name[21]) {
case 't':
if (util::strieq_l("tls_client_fingerprin", name, 21)) {
return SHRPX_LOGF_TLS_CLIENT_FINGERPRINT;
}
break;
}
break;
case 23:
switch (name[22]) {
case 'e':
@ -528,6 +519,24 @@ LogFragmentType log_var_lookup_token(const char *name, size_t namelen) {
break;
}
break;
case 27:
switch (name[26]) {
case '1':
if (util::strieq_l("tls_client_fingerprint_sha", name, 26)) {
return SHRPX_LOGF_TLS_CLIENT_FINGERPRINT_SHA1;
}
break;
}
break;
case 29:
switch (name[28]) {
case '6':
if (util::strieq_l("tls_client_fingerprint_sha25", name, 28)) {
return SHRPX_LOGF_TLS_CLIENT_FINGERPRINT_SHA256;
}
break;
}
break;
}
return SHRPX_LOGF_NONE;
}

View File

@ -533,7 +533,8 @@ void upstream_accesslog(const std::vector<LogFragment> &lfv,
}
std::tie(p, last) = copy_escape(lgsp.sni, p, last);
break;
case SHRPX_LOGF_TLS_CLIENT_FINGERPRINT: {
case SHRPX_LOGF_TLS_CLIENT_FINGERPRINT_SHA1:
case SHRPX_LOGF_TLS_CLIENT_FINGERPRINT_SHA256: {
if (!lgsp.ssl) {
std::tie(p, last) = copy('-', p, last);
break;
@ -544,8 +545,10 @@ void upstream_accesslog(const std::vector<LogFragment> &lfv,
break;
}
std::array<uint8_t, 32> buf;
auto len =
tls::get_x509_fingerprint(buf.data(), buf.size(), x, EVP_sha256());
auto len = tls::get_x509_fingerprint(
buf.data(), buf.size(), x,
lf.type == SHRPX_LOGF_TLS_CLIENT_FINGERPRINT_SHA256 ? EVP_sha256()
: EVP_sha1());
X509_free(x);
if (len <= 0) {
std::tie(p, last) = copy('-', p, last);

View File

@ -138,7 +138,8 @@ enum LogFragmentType {
SHRPX_LOGF_TLS_SESSION_REUSED,
SHRPX_LOGF_SSL_SESSION_REUSED = SHRPX_LOGF_TLS_SESSION_REUSED,
SHRPX_LOGF_TLS_SNI,
SHRPX_LOGF_TLS_CLIENT_FINGERPRINT,
SHRPX_LOGF_TLS_CLIENT_FINGERPRINT_SHA1,
SHRPX_LOGF_TLS_CLIENT_FINGERPRINT_SHA256,
SHRPX_LOGF_TLS_CLIENT_SUBJECT_NAME,
SHRPX_LOGF_BACKEND_HOST,
SHRPX_LOGF_BACKEND_PORT,

View File

@ -142,7 +142,7 @@ mrb_value env_get_tls_sni(mrb_state *mrb, mrb_value self) {
} // namespace
namespace {
mrb_value env_get_tls_client_fingerprint(mrb_state *mrb, mrb_value self) {
mrb_value env_get_tls_client_fingerprint_md(mrb_state *mrb, const EVP_MD *md) {
auto data = static_cast<MRubyAssocData *>(mrb->ud);
auto downstream = data->downstream;
auto upstream = downstream->get_upstream();
@ -158,10 +158,9 @@ mrb_value env_get_tls_client_fingerprint(mrb_state *mrb, mrb_value self) {
return mrb_str_new_static(mrb, "", 0);
}
// Fingerprint is SHA-256, so we need 32 bytes buffer.
// Currently the largest hash value is SHA-256, which is 32 bytes.
std::array<uint8_t, 32> buf;
auto slen =
tls::get_x509_fingerprint(buf.data(), buf.size(), x, EVP_sha256());
auto slen = tls::get_x509_fingerprint(buf.data(), buf.size(), x, md);
X509_free(x);
if (slen == -1) {
mrb_raise(mrb, E_RUNTIME_ERROR, "could not compute client fingerprint");
@ -175,6 +174,19 @@ mrb_value env_get_tls_client_fingerprint(mrb_state *mrb, mrb_value self) {
}
} // namespace
namespace {
mrb_value env_get_tls_client_fingerprint_sha256(mrb_state *mrb,
mrb_value self) {
return env_get_tls_client_fingerprint_md(mrb, EVP_sha256());
}
} // namespace
namespace {
mrb_value env_get_tls_client_fingerprint_sha1(mrb_state *mrb, mrb_value self) {
return env_get_tls_client_fingerprint_md(mrb, EVP_sha1());
}
} // namespace
namespace {
mrb_value env_get_tls_client_subject_name(mrb_state *mrb, mrb_value self) {
auto data = static_cast<MRubyAssocData *>(mrb->ud);
@ -304,8 +316,10 @@ void init_env_class(mrb_state *mrb, RClass *module) {
MRB_ARGS_NONE());
mrb_define_method(mrb, env_class, "tls_sni", env_get_tls_sni,
MRB_ARGS_NONE());
mrb_define_method(mrb, env_class, "tls_client_fingerprint",
env_get_tls_client_fingerprint, MRB_ARGS_NONE());
mrb_define_method(mrb, env_class, "tls_client_fingerprint_sha256",
env_get_tls_client_fingerprint_sha256, MRB_ARGS_NONE());
mrb_define_method(mrb, env_class, "tls_client_fingerprint_sha1",
env_get_tls_client_fingerprint_sha1, MRB_ARGS_NONE());
mrb_define_method(mrb, env_class, "tls_client_subject_name",
env_get_tls_client_subject_name, MRB_ARGS_NONE());
mrb_define_method(mrb, env_class, "tls_cipher", env_get_tls_cipher,