Merge pull request #1123 from nghttp2/mruby-client-cert-not-before-after
nghttpx: Add mruby tls_client_not_before, and tls_client_not_after
This commit is contained in:
commit
65157811d4
|
@ -388,6 +388,16 @@ respectively.
|
|||
|
||||
Return the serial number of a client certificate.
|
||||
|
||||
.. rb:attr_reader:: tls_client_not_before
|
||||
|
||||
Return the start date of a client certificate in seconds since
|
||||
the epoch.
|
||||
|
||||
.. rb:attr_reader:: tls_client_not_after
|
||||
|
||||
Return the end date of a client certificate in seconds since
|
||||
the epoch.
|
||||
|
||||
.. rb:attr_reader:: tls_cipher
|
||||
|
||||
Return a TLS cipher negotiated in this connection.
|
||||
|
|
|
@ -259,6 +259,58 @@ mrb_value env_get_tls_client_serial(mrb_state *mrb, mrb_value self) {
|
|||
}
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
mrb_value env_get_tls_client_not_before(mrb_state *mrb, mrb_value self) {
|
||||
auto data = static_cast<MRubyAssocData *>(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_fixnum_value(0);
|
||||
}
|
||||
|
||||
auto x = SSL_get_peer_certificate(ssl);
|
||||
if (!x) {
|
||||
return mrb_fixnum_value(0);
|
||||
}
|
||||
|
||||
time_t t;
|
||||
if (tls::get_x509_not_before(t, x) != 0) {
|
||||
return mrb_fixnum_value(0);
|
||||
}
|
||||
|
||||
return mrb_fixnum_value(t);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
mrb_value env_get_tls_client_not_after(mrb_state *mrb, mrb_value self) {
|
||||
auto data = static_cast<MRubyAssocData *>(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_fixnum_value(0);
|
||||
}
|
||||
|
||||
auto x = SSL_get_peer_certificate(ssl);
|
||||
if (!x) {
|
||||
return mrb_fixnum_value(0);
|
||||
}
|
||||
|
||||
time_t t;
|
||||
if (tls::get_x509_not_after(t, x) != 0) {
|
||||
return mrb_fixnum_value(0);
|
||||
}
|
||||
|
||||
return mrb_fixnum_value(t);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
mrb_value env_get_tls_cipher(mrb_state *mrb, mrb_value self) {
|
||||
auto data = static_cast<MRubyAssocData *>(mrb->ud);
|
||||
|
@ -374,6 +426,10 @@ void init_env_class(mrb_state *mrb, RClass *module) {
|
|||
env_get_tls_client_subject_name, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, env_class, "tls_client_serial",
|
||||
env_get_tls_client_serial, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, env_class, "tls_client_not_before",
|
||||
env_get_tls_client_not_before, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, env_class, "tls_client_not_after",
|
||||
env_get_tls_client_not_after, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, env_class, "tls_cipher", env_get_tls_cipher,
|
||||
MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, env_class, "tls_protocol", env_get_tls_protocol,
|
||||
|
|
|
@ -64,6 +64,7 @@
|
|||
#include "tls.h"
|
||||
#include "template.h"
|
||||
#include "ssl_compat.h"
|
||||
#include "timegm.h"
|
||||
|
||||
using namespace nghttp2;
|
||||
|
||||
|
@ -1992,6 +1993,74 @@ StringRef get_x509_serial(BlockAllocator &balloc, X509 *x) {
|
|||
#endif // !OPENSSL_1_1_API
|
||||
}
|
||||
|
||||
namespace {
|
||||
// Performs conversion from |at| to time_t. The result is stored in
|
||||
// |t|. This function returns 0 if it succeeds, or -1.
|
||||
int time_t_from_asn1_time(time_t &t, const ASN1_TIME *at) {
|
||||
int rv;
|
||||
|
||||
#if OPENSSL_1_1_1_API
|
||||
struct tm tm;
|
||||
rv = ASN1_TIME_to_tm(at, &tm);
|
||||
if (rv != 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
t = nghttp2_timegm(&tm);
|
||||
#else // !OPENSSL_1_1_1_API
|
||||
auto b = BIO_new(BIO_s_mem());
|
||||
if (!b) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto bio_deleter = defer(BIO_free, b);
|
||||
|
||||
rv = ASN1_TIME_print(b, at);
|
||||
if (rv != 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsigned char *s;
|
||||
auto slen = BIO_get_mem_data(b, &s);
|
||||
auto tt = util::parse_openssl_asn1_time_print(
|
||||
StringRef{s, static_cast<size_t>(slen)});
|
||||
if (tt == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
t = tt;
|
||||
#endif // !OPENSSL_1_1_1_API
|
||||
|
||||
return 0;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
int get_x509_not_before(time_t &t, X509 *x) {
|
||||
#if OPENSSL_1_1_API
|
||||
auto at = X509_get0_notBefore(x);
|
||||
#else // !OPENSSL_1_1_API
|
||||
auto at = X509_get_notBefore(x);
|
||||
#endif // !OPENSSL_1_1_API
|
||||
if (!at) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return time_t_from_asn1_time(t, at);
|
||||
}
|
||||
|
||||
int get_x509_not_after(time_t &t, X509 *x) {
|
||||
#if OPENSSL_1_1_API
|
||||
auto at = X509_get0_notAfter(x);
|
||||
#else // !OPENSSL_1_1_API
|
||||
auto at = X509_get_notAfter(x);
|
||||
#endif // !OPENSSL_1_1_API
|
||||
if (!at) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return time_t_from_asn1_time(t, at);
|
||||
}
|
||||
|
||||
} // namespace tls
|
||||
|
||||
} // namespace shrpx
|
||||
|
|
|
@ -288,6 +288,14 @@ StringRef get_x509_issuer_name(BlockAllocator &balloc, X509 *x);
|
|||
// number, it returns an empty string. number
|
||||
StringRef get_x509_serial(BlockAllocator &balloc, X509 *x);
|
||||
|
||||
// Fills NotBefore of |x| in |t|. This function returns 0 if it
|
||||
// succeeds, or -1.
|
||||
int get_x509_not_before(time_t &t, X509 *x);
|
||||
|
||||
// Fills NotAfter of |x| in |t|. This function returns 0 if it
|
||||
// succeeds, or -1.
|
||||
int get_x509_not_after(time_t &t, X509 *x);
|
||||
|
||||
} // namespace tls
|
||||
|
||||
} // namespace shrpx
|
||||
|
|
|
@ -407,6 +407,15 @@ time_t parse_http_date(const StringRef &s) {
|
|||
#endif // !_WIN32
|
||||
}
|
||||
|
||||
time_t parse_openssl_asn1_time_print(const StringRef &s) {
|
||||
tm tm{};
|
||||
auto r = strptime(s.c_str(), "%b %d %H:%M:%S %Y GMT", &tm);
|
||||
if (r == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
return nghttp2_timegm_without_yday(&tm);
|
||||
}
|
||||
|
||||
char upcase(char c) {
|
||||
if ('a' <= c && c <= 'z') {
|
||||
return c - 'a' + 'A';
|
||||
|
|
|
@ -196,6 +196,11 @@ char *iso8601_date(char *res, int64_t ms);
|
|||
|
||||
time_t parse_http_date(const StringRef &s);
|
||||
|
||||
// Parses time formatted as "MMM DD HH:MM:SS YYYY [GMT]" (e.g., Feb 3
|
||||
// 00:55:52 2015 GMT), which is specifically used by OpenSSL
|
||||
// ASN1_TIME_print().
|
||||
time_t parse_openssl_asn1_time_print(const StringRef &s);
|
||||
|
||||
char upcase(char c);
|
||||
|
||||
inline char lowcase(char c) {
|
||||
|
|
Loading…
Reference in New Issue