From 22502182d0cb3472ba9f1b4624765aee13e186e0 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Wed, 15 Nov 2017 23:41:47 +0900 Subject: [PATCH] Add tls_client_issuer_name log variable and expose it to mruby --- doc/nghttpx.h2r | 4 ++++ gennghttpxfun.py | 1 + src/shrpx.cc | 2 ++ src/shrpx_config.cc | 9 +++++++++ src/shrpx_log.cc | 5 ++++- src/shrpx_log.h | 1 + src/shrpx_mruby_module_env.cc | 26 ++++++++++++++++++++++++++ src/shrpx_tls.cc | 14 +++++++++++--- src/shrpx_tls.h | 4 ++++ 9 files changed, 62 insertions(+), 4 deletions(-) diff --git a/doc/nghttpx.h2r b/doc/nghttpx.h2r index 107a0108..0ae9b3ce 100644 --- a/doc/nghttpx.h2r +++ b/doc/nghttpx.h2r @@ -376,6 +376,10 @@ respectively. Return the SHA-1 fingerprint of a client certificate. + .. rb:attr_reader:: tls_client_issuer_name + + Return the issuer name of a client certificate. + .. rb:attr_reader:: tls_client_subject_name Return the subject name of a client certificate. diff --git a/gennghttpxfun.py b/gennghttpxfun.py index 054444aa..ddfba421 100755 --- a/gennghttpxfun.py +++ b/gennghttpxfun.py @@ -194,6 +194,7 @@ LOGVARS = [ "tls_client_fingerprint_sha256", "tls_client_fingerprint_sha1", "tls_client_subject_name", + "tls_client_issuer_name", "backend_host", "backend_port", ] diff --git a/src/shrpx.cc b/src/shrpx.cc index 41075553..a4f145b2 100644 --- a/src/shrpx.cc +++ b/src/shrpx.cc @@ -2500,6 +2500,8 @@ Logging: client certificate. * $tls_client_subject_name: subject name in client certificate. + * $tls_client_issuer_name: issuer name in client + certificate. * $tls_protocol: protocol for SSL/TLS connection. * $tls_session_id: session ID for SSL/TLS connection. * $tls_session_reused: "r" if SSL/TLS session was diff --git a/src/shrpx_config.cc b/src/shrpx_config.cc index 3344975d..f30e2522 100644 --- a/src/shrpx_config.cc +++ b/src/shrpx_config.cc @@ -510,6 +510,15 @@ LogFragmentType log_var_lookup_token(const char *name, size_t namelen) { break; } break; + case 22: + switch (name[21]) { + case 'e': + if (util::strieq_l("tls_client_issuer_nam", name, 21)) { + return SHRPX_LOGF_TLS_CLIENT_ISSUER_NAME; + } + break; + } + break; case 23: switch (name[22]) { case 'e': diff --git a/src/shrpx_log.cc b/src/shrpx_log.cc index 84624eaa..cc9f9da2 100644 --- a/src/shrpx_log.cc +++ b/src/shrpx_log.cc @@ -557,6 +557,7 @@ void upstream_accesslog(const std::vector &lfv, std::tie(p, last) = copy_hex_low(buf.data(), len, p, last); break; } + case SHRPX_LOGF_TLS_CLIENT_ISSUER_NAME: case SHRPX_LOGF_TLS_CLIENT_SUBJECT_NAME: { if (!lgsp.ssl) { std::tie(p, last) = copy('-', p, last); @@ -567,7 +568,9 @@ void upstream_accesslog(const std::vector &lfv, std::tie(p, last) = copy('-', p, last); break; } - auto name = tls::get_x509_subject_name(balloc, x); + auto name = lf.type == SHRPX_LOGF_TLS_CLIENT_ISSUER_NAME + ? tls::get_x509_issuer_name(balloc, x) + : tls::get_x509_subject_name(balloc, x); X509_free(x); if (name.empty()) { std::tie(p, last) = copy('-', p, last); diff --git a/src/shrpx_log.h b/src/shrpx_log.h index 9584e6ae..0e4e106e 100644 --- a/src/shrpx_log.h +++ b/src/shrpx_log.h @@ -140,6 +140,7 @@ enum LogFragmentType { SHRPX_LOGF_TLS_SNI, SHRPX_LOGF_TLS_CLIENT_FINGERPRINT_SHA1, SHRPX_LOGF_TLS_CLIENT_FINGERPRINT_SHA256, + SHRPX_LOGF_TLS_CLIENT_ISSUER_NAME, SHRPX_LOGF_TLS_CLIENT_SUBJECT_NAME, SHRPX_LOGF_BACKEND_HOST, SHRPX_LOGF_BACKEND_PORT, diff --git a/src/shrpx_mruby_module_env.cc b/src/shrpx_mruby_module_env.cc index 9805e078..982e728f 100644 --- a/src/shrpx_mruby_module_env.cc +++ b/src/shrpx_mruby_module_env.cc @@ -211,6 +211,30 @@ mrb_value env_get_tls_client_subject_name(mrb_state *mrb, mrb_value self) { } } // namespace +namespace { +mrb_value env_get_tls_client_issuer_name(mrb_state *mrb, mrb_value self) { + auto data = static_cast(mrb->ud); + auto downstream = data->downstream; + auto upstream = downstream->get_upstream(); + auto handler = upstream->get_client_handler(); + auto ssl = handler->get_ssl(); + + if (!ssl) { + return mrb_str_new_static(mrb, "", 0); + } + + auto x = SSL_get_peer_certificate(ssl); + if (!x) { + return mrb_str_new_static(mrb, "", 0); + } + + auto &balloc = downstream->get_block_allocator(); + auto name = tls::get_x509_issuer_name(balloc, x); + X509_free(x); + return mrb_str_new(mrb, name.c_str(), name.size()); +} +} // namespace + namespace { mrb_value env_get_tls_cipher(mrb_state *mrb, mrb_value self) { auto data = static_cast(mrb->ud); @@ -320,6 +344,8 @@ void init_env_class(mrb_state *mrb, RClass *module) { 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_issuer_name", + env_get_tls_client_issuer_name, 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, diff --git a/src/shrpx_tls.cc b/src/shrpx_tls.cc index 8126b5ce..6f5327cf 100644 --- a/src/shrpx_tls.cc +++ b/src/shrpx_tls.cc @@ -1929,9 +1929,8 @@ ssize_t get_x509_fingerprint(uint8_t *dst, size_t dstlen, const X509 *x, return len; } -StringRef get_x509_subject_name(BlockAllocator &balloc, X509 *x) { - auto nm = X509_get_subject_name(x); - +namespace { +StringRef get_x509_name(BlockAllocator &balloc, X509_NAME *nm) { auto b = BIO_new(BIO_s_mem()); if (!b) { return StringRef{}; @@ -1950,6 +1949,15 @@ StringRef get_x509_subject_name(BlockAllocator &balloc, X509 *x) { iov.base[slen] = '\0'; return StringRef{iov.base, static_cast(slen)}; } +} // namespace + +StringRef get_x509_subject_name(BlockAllocator &balloc, X509 *x) { + return get_x509_name(balloc, X509_get_subject_name(x)); +} + +StringRef get_x509_issuer_name(BlockAllocator &balloc, X509 *x) { + return get_x509_name(balloc, X509_get_issuer_name(x)); +} } // namespace tls diff --git a/src/shrpx_tls.h b/src/shrpx_tls.h index 87ed7f3e..17ecaf40 100644 --- a/src/shrpx_tls.h +++ b/src/shrpx_tls.h @@ -280,6 +280,10 @@ ssize_t get_x509_fingerprint(uint8_t *dst, size_t dstlen, const X509 *x, // name, it returns an empty string. StringRef get_x509_subject_name(BlockAllocator &balloc, X509 *x); +// Returns issuer name of |x|. If this function fails to get issuer +// name, it returns an empty string. +StringRef get_x509_issuer_name(BlockAllocator &balloc, X509 *x); + } // namespace tls } // namespace shrpx