2 * nghttp2 - HTTP/2 C Library
4 * Copyright (c) 2015 Tatsuhiro Tsujikawa
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 #include "shrpx_mruby_module_env.h"
27 #include <mruby/variable.h>
28 #include <mruby/string.h>
29 #include <mruby/hash.h>
31 #include "shrpx_downstream.h"
32 #include "shrpx_upstream.h"
33 #include "shrpx_client_handler.h"
34 #include "shrpx_mruby.h"
35 #include "shrpx_mruby_module.h"
36 #include "shrpx_log.h"
37 #include "shrpx_tls.h"
44 mrb_value env_init(mrb_state *mrb, mrb_value self) { return self; }
48 mrb_value env_get_req(mrb_state *mrb, mrb_value self) {
49 return mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "req"));
54 mrb_value env_get_resp(mrb_state *mrb, mrb_value self) {
55 return mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "resp"));
60 mrb_value env_get_ctx(mrb_state *mrb, mrb_value self) {
61 auto data = reinterpret_cast<MRubyAssocData *>(mrb->ud);
62 auto downstream = data->downstream;
64 auto dsym = intern_ptr(mrb, downstream);
66 auto ctx = mrb_iv_get(mrb, self, dsym);
68 ctx = mrb_hash_new(mrb);
69 mrb_iv_set(mrb, self, dsym, ctx);
77 mrb_value env_get_phase(mrb_state *mrb, mrb_value self) {
78 auto data = static_cast<MRubyAssocData *>(mrb->ud);
80 return mrb_fixnum_value(data->phase);
85 mrb_value env_get_remote_addr(mrb_state *mrb, mrb_value self) {
86 auto data = static_cast<MRubyAssocData *>(mrb->ud);
87 auto downstream = data->downstream;
88 auto upstream = downstream->get_upstream();
89 auto handler = upstream->get_client_handler();
91 auto &ipaddr = handler->get_ipaddr();
93 return mrb_str_new(mrb, ipaddr.c_str(), ipaddr.size());
98 mrb_value env_get_server_port(mrb_state *mrb, mrb_value self) {
99 auto data = static_cast<MRubyAssocData *>(mrb->ud);
100 auto downstream = data->downstream;
101 auto upstream = downstream->get_upstream();
102 auto handler = upstream->get_client_handler();
103 auto faddr = handler->get_upstream_addr();
105 return mrb_fixnum_value(faddr->port);
110 mrb_value env_get_server_addr(mrb_state *mrb, mrb_value self) {
111 auto data = static_cast<MRubyAssocData *>(mrb->ud);
112 auto downstream = data->downstream;
113 auto upstream = downstream->get_upstream();
114 auto handler = upstream->get_client_handler();
115 auto faddr = handler->get_upstream_addr();
117 return mrb_str_new(mrb, faddr->host.c_str(), faddr->host.size());
122 mrb_value env_get_tls_used(mrb_state *mrb, mrb_value self) {
123 auto data = static_cast<MRubyAssocData *>(mrb->ud);
124 auto downstream = data->downstream;
125 auto upstream = downstream->get_upstream();
126 auto handler = upstream->get_client_handler();
128 return handler->get_ssl() ? mrb_true_value() : mrb_false_value();
133 mrb_value env_get_tls_sni(mrb_state *mrb, mrb_value self) {
134 auto data = static_cast<MRubyAssocData *>(mrb->ud);
135 auto downstream = data->downstream;
136 auto upstream = downstream->get_upstream();
137 auto handler = upstream->get_client_handler();
138 auto sni = handler->get_tls_sni();
140 return mrb_str_new(mrb, sni.c_str(), sni.size());
145 mrb_value env_get_tls_client_fingerprint_md(mrb_state *mrb, const EVP_MD *md) {
146 auto data = static_cast<MRubyAssocData *>(mrb->ud);
147 auto downstream = data->downstream;
148 auto upstream = downstream->get_upstream();
149 auto handler = upstream->get_client_handler();
150 auto ssl = handler->get_ssl();
153 return mrb_str_new_static(mrb, "", 0);
156 #if OPENSSL_3_0_0_API
157 auto x = SSL_get0_peer_certificate(ssl);
158 #else // !OPENSSL_3_0_0_API
159 auto x = SSL_get_peer_certificate(ssl);
160 #endif // !OPENSSL_3_0_0_API
162 return mrb_str_new_static(mrb, "", 0);
165 // Currently the largest hash value is SHA-256, which is 32 bytes.
166 std::array<uint8_t, 32> buf;
167 auto slen = tls::get_x509_fingerprint(buf.data(), buf.size(), x, md);
168 #if !OPENSSL_3_0_0_API
170 #endif // !OPENSSL_3_0_0_API
172 mrb_raise(mrb, E_RUNTIME_ERROR, "could not compute client fingerprint");
175 // TODO Use template version of format_hex
176 auto &balloc = downstream->get_block_allocator();
177 auto f = util::format_hex(balloc,
178 StringRef{std::begin(buf), std::begin(buf) + slen});
179 return mrb_str_new(mrb, f.c_str(), f.size());
184 mrb_value env_get_tls_client_fingerprint_sha256(mrb_state *mrb,
186 return env_get_tls_client_fingerprint_md(mrb, EVP_sha256());
191 mrb_value env_get_tls_client_fingerprint_sha1(mrb_state *mrb, mrb_value self) {
192 return env_get_tls_client_fingerprint_md(mrb, EVP_sha1());
197 mrb_value env_get_tls_client_subject_name(mrb_state *mrb, mrb_value self) {
198 auto data = static_cast<MRubyAssocData *>(mrb->ud);
199 auto downstream = data->downstream;
200 auto upstream = downstream->get_upstream();
201 auto handler = upstream->get_client_handler();
202 auto ssl = handler->get_ssl();
205 return mrb_str_new_static(mrb, "", 0);
208 #if OPENSSL_3_0_0_API
209 auto x = SSL_get0_peer_certificate(ssl);
210 #else // !OPENSSL_3_0_0_API
211 auto x = SSL_get_peer_certificate(ssl);
212 #endif // !OPENSSL_3_0_0_API
214 return mrb_str_new_static(mrb, "", 0);
217 auto &balloc = downstream->get_block_allocator();
218 auto name = tls::get_x509_subject_name(balloc, x);
219 #if !OPENSSL_3_0_0_API
221 #endif // !OPENSSL_3_0_0_API
222 return mrb_str_new(mrb, name.c_str(), name.size());
227 mrb_value env_get_tls_client_issuer_name(mrb_state *mrb, mrb_value self) {
228 auto data = static_cast<MRubyAssocData *>(mrb->ud);
229 auto downstream = data->downstream;
230 auto upstream = downstream->get_upstream();
231 auto handler = upstream->get_client_handler();
232 auto ssl = handler->get_ssl();
235 return mrb_str_new_static(mrb, "", 0);
238 #if OPENSSL_3_0_0_API
239 auto x = SSL_get0_peer_certificate(ssl);
240 #else // !OPENSSL_3_0_0_API
241 auto x = SSL_get_peer_certificate(ssl);
242 #endif // !OPENSSL_3_0_0_API
244 return mrb_str_new_static(mrb, "", 0);
247 auto &balloc = downstream->get_block_allocator();
248 auto name = tls::get_x509_issuer_name(balloc, x);
249 #if !OPENSSL_3_0_0_API
251 #endif // !OPENSSL_3_0_0_API
252 return mrb_str_new(mrb, name.c_str(), name.size());
257 mrb_value env_get_tls_client_serial(mrb_state *mrb, mrb_value self) {
258 auto data = static_cast<MRubyAssocData *>(mrb->ud);
259 auto downstream = data->downstream;
260 auto upstream = downstream->get_upstream();
261 auto handler = upstream->get_client_handler();
262 auto ssl = handler->get_ssl();
265 return mrb_str_new_static(mrb, "", 0);
268 #if OPENSSL_3_0_0_API
269 auto x = SSL_get0_peer_certificate(ssl);
270 #else // !OPENSSL_3_0_0_API
271 auto x = SSL_get_peer_certificate(ssl);
272 #endif // !OPENSSL_3_0_0_API
274 return mrb_str_new_static(mrb, "", 0);
277 auto &balloc = downstream->get_block_allocator();
278 auto sn = tls::get_x509_serial(balloc, x);
279 #if !OPENSSL_3_0_0_API
281 #endif // !OPENSSL_3_0_0_API
282 return mrb_str_new(mrb, sn.c_str(), sn.size());
287 mrb_value env_get_tls_client_not_before(mrb_state *mrb, mrb_value self) {
288 auto data = static_cast<MRubyAssocData *>(mrb->ud);
289 auto downstream = data->downstream;
290 auto upstream = downstream->get_upstream();
291 auto handler = upstream->get_client_handler();
292 auto ssl = handler->get_ssl();
295 return mrb_fixnum_value(0);
298 #if OPENSSL_3_0_0_API
299 auto x = SSL_get0_peer_certificate(ssl);
300 #else // !OPENSSL_3_0_0_API
301 auto x = SSL_get_peer_certificate(ssl);
302 #endif // !OPENSSL_3_0_0_API
304 return mrb_fixnum_value(0);
308 if (tls::get_x509_not_before(t, x) != 0) {
312 #if !OPENSSL_3_0_0_API
314 #endif // !OPENSSL_3_0_0_API
316 return mrb_fixnum_value(t);
321 mrb_value env_get_tls_client_not_after(mrb_state *mrb, mrb_value self) {
322 auto data = static_cast<MRubyAssocData *>(mrb->ud);
323 auto downstream = data->downstream;
324 auto upstream = downstream->get_upstream();
325 auto handler = upstream->get_client_handler();
326 auto ssl = handler->get_ssl();
329 return mrb_fixnum_value(0);
332 #if OPENSSL_3_0_0_API
333 auto x = SSL_get0_peer_certificate(ssl);
334 #else // !OPENSSL_3_0_0_API
335 auto x = SSL_get_peer_certificate(ssl);
336 #endif // !OPENSSL_3_0_0_API
338 return mrb_fixnum_value(0);
342 if (tls::get_x509_not_after(t, x) != 0) {
346 #if !OPENSSL_3_0_0_API
348 #endif // !OPENSSL_3_0_0_API
350 return mrb_fixnum_value(t);
355 mrb_value env_get_tls_cipher(mrb_state *mrb, mrb_value self) {
356 auto data = static_cast<MRubyAssocData *>(mrb->ud);
357 auto downstream = data->downstream;
358 auto upstream = downstream->get_upstream();
359 auto handler = upstream->get_client_handler();
360 auto ssl = handler->get_ssl();
363 return mrb_str_new_static(mrb, "", 0);
366 return mrb_str_new_cstr(mrb, SSL_get_cipher_name(ssl));
371 mrb_value env_get_tls_protocol(mrb_state *mrb, mrb_value self) {
372 auto data = static_cast<MRubyAssocData *>(mrb->ud);
373 auto downstream = data->downstream;
374 auto upstream = downstream->get_upstream();
375 auto handler = upstream->get_client_handler();
376 auto ssl = handler->get_ssl();
379 return mrb_str_new_static(mrb, "", 0);
382 return mrb_str_new_cstr(mrb, nghttp2::tls::get_tls_protocol(ssl));
387 mrb_value env_get_tls_session_id(mrb_state *mrb, mrb_value self) {
388 auto data = static_cast<MRubyAssocData *>(mrb->ud);
389 auto downstream = data->downstream;
390 auto upstream = downstream->get_upstream();
391 auto handler = upstream->get_client_handler();
392 auto ssl = handler->get_ssl();
395 return mrb_str_new_static(mrb, "", 0);
398 auto session = SSL_get_session(ssl);
400 return mrb_str_new_static(mrb, "", 0);
403 unsigned int session_id_length = 0;
404 auto session_id = SSL_SESSION_get_id(session, &session_id_length);
406 // TODO Use template version of util::format_hex.
407 auto &balloc = downstream->get_block_allocator();
408 auto id = util::format_hex(balloc, StringRef{session_id, session_id_length});
409 return mrb_str_new(mrb, id.c_str(), id.size());
414 mrb_value env_get_tls_session_reused(mrb_state *mrb, mrb_value self) {
415 auto data = static_cast<MRubyAssocData *>(mrb->ud);
416 auto downstream = data->downstream;
417 auto upstream = downstream->get_upstream();
418 auto handler = upstream->get_client_handler();
419 auto ssl = handler->get_ssl();
422 return mrb_false_value();
425 return SSL_session_reused(ssl) ? mrb_true_value() : mrb_false_value();
430 mrb_value env_get_alpn(mrb_state *mrb, mrb_value self) {
431 auto data = static_cast<MRubyAssocData *>(mrb->ud);
432 auto downstream = data->downstream;
433 auto upstream = downstream->get_upstream();
434 auto handler = upstream->get_client_handler();
435 auto alpn = handler->get_alpn();
436 return mrb_str_new(mrb, alpn.c_str(), alpn.size());
441 mrb_value env_get_tls_handshake_finished(mrb_state *mrb, mrb_value self) {
442 auto data = static_cast<MRubyAssocData *>(mrb->ud);
443 auto downstream = data->downstream;
444 auto upstream = downstream->get_upstream();
445 auto handler = upstream->get_client_handler();
446 auto conn = handler->get_connection();
447 return SSL_is_init_finished(conn->tls.ssl) ? mrb_true_value()
452 void init_env_class(mrb_state *mrb, RClass *module) {
454 mrb_define_class_under(mrb, module, "Env", mrb->object_class);
456 mrb_define_method(mrb, env_class, "initialize", env_init, MRB_ARGS_NONE());
457 mrb_define_method(mrb, env_class, "req", env_get_req, MRB_ARGS_NONE());
458 mrb_define_method(mrb, env_class, "resp", env_get_resp, MRB_ARGS_NONE());
459 mrb_define_method(mrb, env_class, "ctx", env_get_ctx, MRB_ARGS_NONE());
460 mrb_define_method(mrb, env_class, "phase", env_get_phase, MRB_ARGS_NONE());
461 mrb_define_method(mrb, env_class, "remote_addr", env_get_remote_addr,
463 mrb_define_method(mrb, env_class, "server_addr", env_get_server_addr,
465 mrb_define_method(mrb, env_class, "server_port", env_get_server_port,
467 mrb_define_method(mrb, env_class, "tls_used", env_get_tls_used,
469 mrb_define_method(mrb, env_class, "tls_sni", env_get_tls_sni,
471 mrb_define_method(mrb, env_class, "tls_client_fingerprint_sha256",
472 env_get_tls_client_fingerprint_sha256, MRB_ARGS_NONE());
473 mrb_define_method(mrb, env_class, "tls_client_fingerprint_sha1",
474 env_get_tls_client_fingerprint_sha1, MRB_ARGS_NONE());
475 mrb_define_method(mrb, env_class, "tls_client_issuer_name",
476 env_get_tls_client_issuer_name, MRB_ARGS_NONE());
477 mrb_define_method(mrb, env_class, "tls_client_subject_name",
478 env_get_tls_client_subject_name, MRB_ARGS_NONE());
479 mrb_define_method(mrb, env_class, "tls_client_serial",
480 env_get_tls_client_serial, MRB_ARGS_NONE());
481 mrb_define_method(mrb, env_class, "tls_client_not_before",
482 env_get_tls_client_not_before, MRB_ARGS_NONE());
483 mrb_define_method(mrb, env_class, "tls_client_not_after",
484 env_get_tls_client_not_after, MRB_ARGS_NONE());
485 mrb_define_method(mrb, env_class, "tls_cipher", env_get_tls_cipher,
487 mrb_define_method(mrb, env_class, "tls_protocol", env_get_tls_protocol,
489 mrb_define_method(mrb, env_class, "tls_session_id", env_get_tls_session_id,
491 mrb_define_method(mrb, env_class, "tls_session_reused",
492 env_get_tls_session_reused, MRB_ARGS_NONE());
493 mrb_define_method(mrb, env_class, "alpn", env_get_alpn, MRB_ARGS_NONE());
494 mrb_define_method(mrb, env_class, "tls_handshake_finished",
495 env_get_tls_handshake_finished, MRB_ARGS_NONE());