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.
|
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
|
.. rb:attr_reader:: tls_cipher
|
||||||
|
|
||||||
Return a TLS cipher negotiated in this connection.
|
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
|
||||||
|
|
||||||
|
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 {
|
namespace {
|
||||||
mrb_value env_get_tls_cipher(mrb_state *mrb, mrb_value self) {
|
mrb_value env_get_tls_cipher(mrb_state *mrb, mrb_value self) {
|
||||||
auto data = static_cast<MRubyAssocData *>(mrb->ud);
|
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());
|
env_get_tls_client_subject_name, MRB_ARGS_NONE());
|
||||||
mrb_define_method(mrb, env_class, "tls_client_serial",
|
mrb_define_method(mrb, env_class, "tls_client_serial",
|
||||||
env_get_tls_client_serial, MRB_ARGS_NONE());
|
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_define_method(mrb, env_class, "tls_cipher", env_get_tls_cipher,
|
||||||
MRB_ARGS_NONE());
|
MRB_ARGS_NONE());
|
||||||
mrb_define_method(mrb, env_class, "tls_protocol", env_get_tls_protocol,
|
mrb_define_method(mrb, env_class, "tls_protocol", env_get_tls_protocol,
|
||||||
|
|
|
@ -64,6 +64,7 @@
|
||||||
#include "tls.h"
|
#include "tls.h"
|
||||||
#include "template.h"
|
#include "template.h"
|
||||||
#include "ssl_compat.h"
|
#include "ssl_compat.h"
|
||||||
|
#include "timegm.h"
|
||||||
|
|
||||||
using namespace nghttp2;
|
using namespace nghttp2;
|
||||||
|
|
||||||
|
@ -1992,6 +1993,74 @@ StringRef get_x509_serial(BlockAllocator &balloc, X509 *x) {
|
||||||
#endif // !OPENSSL_1_1_API
|
#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 tls
|
||||||
|
|
||||||
} // namespace shrpx
|
} // namespace shrpx
|
||||||
|
|
|
@ -288,6 +288,14 @@ StringRef get_x509_issuer_name(BlockAllocator &balloc, X509 *x);
|
||||||
// number, it returns an empty string. number
|
// number, it returns an empty string. number
|
||||||
StringRef get_x509_serial(BlockAllocator &balloc, X509 *x);
|
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 tls
|
||||||
|
|
||||||
} // namespace shrpx
|
} // namespace shrpx
|
||||||
|
|
|
@ -407,6 +407,15 @@ time_t parse_http_date(const StringRef &s) {
|
||||||
#endif // !_WIN32
|
#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) {
|
char upcase(char c) {
|
||||||
if ('a' <= c && c <= 'z') {
|
if ('a' <= c && c <= 'z') {
|
||||||
return c - 'a' + 'A';
|
return c - 'a' + 'A';
|
||||||
|
|
|
@ -196,6 +196,11 @@ char *iso8601_date(char *res, int64_t ms);
|
||||||
|
|
||||||
time_t parse_http_date(const StringRef &s);
|
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);
|
char upcase(char c);
|
||||||
|
|
||||||
inline char lowcase(char c) {
|
inline char lowcase(char c) {
|
||||||
|
|
Loading…
Reference in New Issue