@@ -49,7 +49,7 @@ static ID id_i_cert_store, id_i_ca_file, id_i_ca_path, id_i_verify_mode,
49
49
id_i_session_id_context , id_i_session_get_cb , id_i_session_new_cb ,
50
50
id_i_session_remove_cb , id_i_npn_select_cb , id_i_npn_protocols ,
51
51
id_i_alpn_select_cb , id_i_alpn_protocols , id_i_servername_cb ,
52
- id_i_verify_hostname ;
52
+ id_i_verify_hostname , id_i_keylog_cb ;
53
53
static ID id_i_io , id_i_context , id_i_hostname ;
54
54
55
55
static int ossl_ssl_ex_vcb_idx ;
@@ -441,6 +441,54 @@ ossl_sslctx_session_new_cb(SSL *ssl, SSL_SESSION *sess)
441
441
return 0 ;
442
442
}
443
443
444
+ #if OPENSSL_VERSION_NUMBER >= 0x10101000 && !defined(LIBRESSL_VERSION_NUMBER )
445
+ /*
446
+ * It is only compatible with OpenSSL >= 1.1.1. Even if LibreSSL implements
447
+ * SSL_CTX_set_keylog_callback() from v3.4.2, it does nothing (see
448
+ * https://github.com/libressl-portable/openbsd/commit/648d39f0f035835d0653342d139883b9661e9cb6).
449
+ */
450
+
451
+ struct ossl_call_keylog_cb_args {
452
+ VALUE ssl_obj ;
453
+ const char * line ;
454
+ };
455
+
456
+ static VALUE
457
+ ossl_call_keylog_cb (VALUE args_v )
458
+ {
459
+ VALUE sslctx_obj , cb , line_v ;
460
+ struct ossl_call_keylog_cb_args * args = (struct ossl_call_keylog_cb_args * ) args_v ;
461
+
462
+ sslctx_obj = rb_attr_get (args -> ssl_obj , id_i_context );
463
+
464
+ cb = rb_attr_get (sslctx_obj , id_i_keylog_cb );
465
+ if (NIL_P (cb )) return Qnil ;
466
+
467
+ line_v = rb_str_new_cstr (args -> line );
468
+
469
+ return rb_funcall (cb , id_call , 2 , args -> ssl_obj , line_v );
470
+ }
471
+
472
+ static void
473
+ ossl_sslctx_keylog_cb (const SSL * ssl , const char * line )
474
+ {
475
+ VALUE ssl_obj ;
476
+ struct ossl_call_keylog_cb_args args ;
477
+ int state = 0 ;
478
+
479
+ OSSL_Debug ("SSL keylog callback entered" );
480
+
481
+ ssl_obj = (VALUE )SSL_get_ex_data (ssl , ossl_ssl_ex_ptr_idx );
482
+ args .ssl_obj = ssl_obj ;
483
+ args .line = line ;
484
+
485
+ rb_protect (ossl_call_keylog_cb , (VALUE )& args , & state );
486
+ if (state ) {
487
+ rb_ivar_set (ssl_obj , ID_callback_state , INT2NUM (state ));
488
+ }
489
+ }
490
+ #endif
491
+
444
492
static VALUE
445
493
ossl_call_session_remove_cb (VALUE ary )
446
494
{
@@ -911,6 +959,18 @@ ossl_sslctx_setup(VALUE self)
911
959
OSSL_Debug ("SSL TLSEXT servername callback added" );
912
960
}
913
961
962
+ #if OPENSSL_VERSION_NUMBER >= 0x10101000 && !defined(LIBRESSL_VERSION_NUMBER )
963
+ /*
964
+ * It is only compatible with OpenSSL >= 1.1.1. Even if LibreSSL implements
965
+ * SSL_CTX_set_keylog_callback() from v3.4.2, it does nothing (see
966
+ * https://github.com/libressl-portable/openbsd/commit/648d39f0f035835d0653342d139883b9661e9cb6).
967
+ */
968
+ if (RTEST (rb_attr_get (self , id_i_keylog_cb ))) {
969
+ SSL_CTX_set_keylog_callback (ctx , ossl_sslctx_keylog_cb );
970
+ OSSL_Debug ("SSL keylog callback added" );
971
+ }
972
+ #endif
973
+
914
974
return Qtrue ;
915
975
}
916
976
@@ -2779,6 +2839,29 @@ Init_ossl_ssl(void)
2779
2839
*/
2780
2840
rb_attr (cSSLContext , rb_intern_const ("alpn_select_cb" ), 1 , 1 , Qfalse );
2781
2841
2842
+ /*
2843
+ * A callback invoked when TLS key material is generated or received, in
2844
+ * order to allow applications to store this keying material for debugging
2845
+ * purposes.
2846
+ *
2847
+ * The callback is invoked with an SSLSocket and a string containing the
2848
+ * key material in the format used by NSS for its SSLKEYLOGFILE debugging
2849
+ * output.
2850
+ *
2851
+ * It is only compatible with OpenSSL >= 1.1.1. Even if LibreSSL implements
2852
+ * SSL_CTX_set_keylog_callback() from v3.4.2, it does nothing (see
2853
+ * https://github.com/libressl-portable/openbsd/commit/648d39f0f035835d0653342d139883b9661e9cb6).
2854
+ *
2855
+ * === Example
2856
+ *
2857
+ * context.keylog_cb = proc do |_sock, line|
2858
+ * File.open('ssl_keylog_file', "a") do |f|
2859
+ * f.write("#{line}\n")
2860
+ * end
2861
+ * end
2862
+ */
2863
+ rb_attr (cSSLContext , rb_intern_const ("keylog_cb" ), 1 , 1 , Qfalse );
2864
+
2782
2865
rb_define_alias (cSSLContext , "ssl_timeout" , "timeout" );
2783
2866
rb_define_alias (cSSLContext , "ssl_timeout=" , "timeout=" );
2784
2867
rb_define_private_method (cSSLContext , "set_minmax_proto_version" ,
@@ -3060,6 +3143,7 @@ Init_ossl_ssl(void)
3060
3143
DefIVarID (alpn_select_cb );
3061
3144
DefIVarID (servername_cb );
3062
3145
DefIVarID (verify_hostname );
3146
+ DefIVarID (keylog_cb );
3063
3147
3064
3148
DefIVarID (io );
3065
3149
DefIVarID (context );
0 commit comments