openssl 2.2.0 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +33 -45
  3. data/History.md +300 -0
  4. data/README.md +36 -19
  5. data/ext/openssl/extconf.rb +119 -79
  6. data/ext/openssl/openssl_missing.c +0 -66
  7. data/ext/openssl/openssl_missing.h +26 -45
  8. data/ext/openssl/ossl.c +131 -233
  9. data/ext/openssl/ossl.h +31 -12
  10. data/ext/openssl/ossl_asn1.c +26 -13
  11. data/ext/openssl/ossl_bn.c +279 -143
  12. data/ext/openssl/ossl_bn.h +2 -1
  13. data/ext/openssl/ossl_cipher.c +13 -14
  14. data/ext/openssl/ossl_config.c +412 -41
  15. data/ext/openssl/ossl_config.h +4 -7
  16. data/ext/openssl/ossl_digest.c +16 -12
  17. data/ext/openssl/ossl_engine.c +17 -16
  18. data/ext/openssl/ossl_hmac.c +57 -136
  19. data/ext/openssl/ossl_kdf.c +12 -4
  20. data/ext/openssl/ossl_ns_spki.c +1 -1
  21. data/ext/openssl/ossl_ocsp.c +11 -59
  22. data/ext/openssl/ossl_pkcs12.c +22 -4
  23. data/ext/openssl/ossl_pkcs7.c +45 -62
  24. data/ext/openssl/ossl_pkey.c +1320 -196
  25. data/ext/openssl/ossl_pkey.h +36 -73
  26. data/ext/openssl/ossl_pkey_dh.c +152 -347
  27. data/ext/openssl/ossl_pkey_dsa.c +157 -413
  28. data/ext/openssl/ossl_pkey_ec.c +227 -343
  29. data/ext/openssl/ossl_pkey_rsa.c +159 -491
  30. data/ext/openssl/ossl_provider.c +211 -0
  31. data/ext/openssl/ossl_provider.h +5 -0
  32. data/ext/openssl/ossl_ssl.c +593 -467
  33. data/ext/openssl/ossl_ssl_session.c +29 -30
  34. data/ext/openssl/ossl_ts.c +67 -42
  35. data/ext/openssl/ossl_x509.c +0 -6
  36. data/ext/openssl/ossl_x509attr.c +1 -1
  37. data/ext/openssl/ossl_x509cert.c +168 -12
  38. data/ext/openssl/ossl_x509crl.c +14 -11
  39. data/ext/openssl/ossl_x509ext.c +14 -9
  40. data/ext/openssl/ossl_x509name.c +10 -3
  41. data/ext/openssl/ossl_x509req.c +14 -11
  42. data/ext/openssl/ossl_x509revoked.c +4 -4
  43. data/ext/openssl/ossl_x509store.c +204 -94
  44. data/lib/openssl/buffering.rb +10 -4
  45. data/lib/openssl/digest.rb +1 -5
  46. data/lib/openssl/hmac.rb +65 -0
  47. data/lib/openssl/pkey.rb +429 -0
  48. data/lib/openssl/ssl.rb +23 -18
  49. data/lib/openssl/version.rb +1 -1
  50. data/lib/openssl/x509.rb +22 -0
  51. data/lib/openssl.rb +0 -1
  52. metadata +13 -68
  53. data/ext/openssl/ruby_missing.h +0 -24
  54. data/lib/openssl/config.rb +0 -501
@@ -11,8 +11,18 @@
11
11
  */
12
12
  #include "ossl.h"
13
13
 
14
+ #ifndef OPENSSL_NO_SOCK
14
15
  #define numberof(ary) (int)(sizeof(ary)/sizeof((ary)[0]))
15
16
 
17
+ #if !defined(OPENSSL_NO_NEXTPROTONEG) && !OSSL_IS_LIBRESSL
18
+ # define OSSL_USE_NEXTPROTONEG
19
+ #endif
20
+
21
+ #if !defined(TLS1_3_VERSION) && \
22
+ OSSL_LIBRESSL_PREREQ(3, 2, 0) && !OSSL_LIBRESSL_PREREQ(3, 4, 0)
23
+ # define TLS1_3_VERSION 0x0304
24
+ #endif
25
+
16
26
  #ifdef _WIN32
17
27
  # define TO_SOCKET(s) _get_osfhandle(s)
18
28
  #else
@@ -24,7 +34,6 @@
24
34
  } while (0)
25
35
 
26
36
  VALUE mSSL;
27
- static VALUE mSSLExtConfig;
28
37
  static VALUE eSSLError;
29
38
  VALUE cSSLContext;
30
39
  VALUE cSSLSocket;
@@ -32,44 +41,43 @@ VALUE cSSLSocket;
32
41
  static VALUE eSSLErrorWaitReadable;
33
42
  static VALUE eSSLErrorWaitWritable;
34
43
 
35
- static ID id_call, ID_callback_state, id_tmp_dh_callback, id_tmp_ecdh_callback,
36
- id_npn_protocols_encoded;
44
+ static ID id_call, ID_callback_state, id_tmp_dh_callback,
45
+ id_npn_protocols_encoded, id_each;
37
46
  static VALUE sym_exception, sym_wait_readable, sym_wait_writable;
38
47
 
39
48
  static ID id_i_cert_store, id_i_ca_file, id_i_ca_path, id_i_verify_mode,
40
49
  id_i_verify_depth, id_i_verify_callback, id_i_client_ca,
41
50
  id_i_renegotiation_cb, id_i_cert, id_i_key, id_i_extra_chain_cert,
42
- id_i_client_cert_cb, id_i_tmp_ecdh_callback, id_i_timeout,
51
+ id_i_client_cert_cb, id_i_timeout,
43
52
  id_i_session_id_context, id_i_session_get_cb, id_i_session_new_cb,
44
53
  id_i_session_remove_cb, id_i_npn_select_cb, id_i_npn_protocols,
45
54
  id_i_alpn_select_cb, id_i_alpn_protocols, id_i_servername_cb,
46
- id_i_verify_hostname;
55
+ id_i_verify_hostname, id_i_keylog_cb;
47
56
  static ID id_i_io, id_i_context, id_i_hostname;
48
57
 
49
58
  static int ossl_ssl_ex_vcb_idx;
50
59
  static int ossl_ssl_ex_ptr_idx;
51
60
  static int ossl_sslctx_ex_ptr_idx;
52
- #if !defined(HAVE_X509_STORE_UP_REF)
53
- static int ossl_sslctx_ex_store_p;
54
- #endif
55
61
 
56
62
  static void
57
- ossl_sslctx_free(void *ptr)
63
+ ossl_sslctx_mark(void *ptr)
58
64
  {
59
65
  SSL_CTX *ctx = ptr;
60
- #if !defined(HAVE_X509_STORE_UP_REF)
61
- if (ctx && SSL_CTX_get_ex_data(ctx, ossl_sslctx_ex_store_p))
62
- ctx->cert_store = NULL;
63
- #endif
64
- SSL_CTX_free(ctx);
66
+ rb_gc_mark((VALUE)SSL_CTX_get_ex_data(ctx, ossl_sslctx_ex_ptr_idx));
67
+ }
68
+
69
+ static void
70
+ ossl_sslctx_free(void *ptr)
71
+ {
72
+ SSL_CTX_free(ptr);
65
73
  }
66
74
 
67
75
  static const rb_data_type_t ossl_sslctx_type = {
68
76
  "OpenSSL/SSL/CTX",
69
77
  {
70
- 0, ossl_sslctx_free,
78
+ ossl_sslctx_mark, ossl_sslctx_free,
71
79
  },
72
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
80
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
73
81
  };
74
82
 
75
83
  static VALUE
@@ -83,7 +91,7 @@ ossl_sslctx_s_alloc(VALUE klass)
83
91
  VALUE obj;
84
92
 
85
93
  obj = TypedData_Wrap_Struct(klass, &ossl_sslctx_type, 0);
86
- #if OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(LIBRESSL_VERSION_NUMBER)
94
+ #if OPENSSL_VERSION_NUMBER >= 0x10100000 || defined(LIBRESSL_VERSION_NUMBER)
87
95
  ctx = SSL_CTX_new(TLS_method());
88
96
  #else
89
97
  ctx = SSL_CTX_new(SSLv23_method());
@@ -95,14 +103,15 @@ ossl_sslctx_s_alloc(VALUE klass)
95
103
  RTYPEDDATA_DATA(obj) = ctx;
96
104
  SSL_CTX_set_ex_data(ctx, ossl_sslctx_ex_ptr_idx, (void *)obj);
97
105
 
98
- #if !defined(OPENSSL_NO_EC) && defined(HAVE_SSL_CTX_SET_ECDH_AUTO)
106
+ #if !defined(OPENSSL_NO_EC) && OPENSSL_VERSION_NUMBER < 0x10100000 && \
107
+ !defined(LIBRESSL_VERSION_NUMBER)
99
108
  /* We use SSL_CTX_set1_curves_list() to specify the curve used in ECDH. It
100
109
  * allows to specify multiple curve names and OpenSSL will select
101
110
  * automatically from them. In OpenSSL 1.0.2, the automatic selection has to
102
- * be enabled explicitly. But OpenSSL 1.1.0 removed the knob and it is
103
- * always enabled. To uniform the behavior, we enable the automatic
104
- * selection also in 1.0.2. Users can still disable ECDH by removing ECDH
105
- * cipher suites by SSLContext#ciphers=. */
111
+ * be enabled explicitly. OpenSSL 1.1.0 and LibreSSL 2.6.1 removed the knob
112
+ * and it is always enabled. To uniform the behavior, we enable the
113
+ * automatic selection also in 1.0.2. Users can still disable ECDH by
114
+ * removing ECDH cipher suites by SSLContext#ciphers=. */
106
115
  if (!SSL_CTX_set_ecdh_auto(ctx, 1))
107
116
  ossl_raise(eSSLError, "SSL_CTX_set_ecdh_auto");
108
117
  #endif
@@ -231,8 +240,7 @@ ossl_client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
231
240
  return 1;
232
241
  }
233
242
 
234
- #if !defined(OPENSSL_NO_DH) || \
235
- !defined(OPENSSL_NO_EC) && defined(HAVE_SSL_CTX_SET_TMP_ECDH_CALLBACK)
243
+ #if !defined(OPENSSL_NO_DH)
236
244
  struct tmp_dh_callback_args {
237
245
  VALUE ssl_obj;
238
246
  ID id;
@@ -241,22 +249,23 @@ struct tmp_dh_callback_args {
241
249
  int keylength;
242
250
  };
243
251
 
244
- static EVP_PKEY *
245
- ossl_call_tmp_dh_callback(struct tmp_dh_callback_args *args)
252
+ static VALUE
253
+ ossl_call_tmp_dh_callback(VALUE arg)
246
254
  {
255
+ struct tmp_dh_callback_args *args = (struct tmp_dh_callback_args *)arg;
247
256
  VALUE cb, dh;
248
257
  EVP_PKEY *pkey;
249
258
 
250
259
  cb = rb_funcall(args->ssl_obj, args->id, 0);
251
260
  if (NIL_P(cb))
252
- return NULL;
261
+ return (VALUE)NULL;
253
262
  dh = rb_funcall(cb, id_call, 3, args->ssl_obj, INT2NUM(args->is_export),
254
263
  INT2NUM(args->keylength));
255
264
  pkey = GetPKeyPtr(dh);
256
265
  if (EVP_PKEY_base_id(pkey) != args->type)
257
- return NULL;
266
+ return (VALUE)NULL;
258
267
 
259
- return pkey;
268
+ return (VALUE)pkey;
260
269
  }
261
270
  #endif
262
271
 
@@ -276,7 +285,7 @@ ossl_tmp_dh_callback(SSL *ssl, int is_export, int keylength)
276
285
  args.keylength = keylength;
277
286
  args.type = EVP_PKEY_DH;
278
287
 
279
- pkey = (EVP_PKEY *)rb_protect((VALUE (*)(VALUE))ossl_call_tmp_dh_callback,
288
+ pkey = (EVP_PKEY *)rb_protect(ossl_call_tmp_dh_callback,
280
289
  (VALUE)&args, &state);
281
290
  if (state) {
282
291
  rb_ivar_set(rb_ssl, ID_callback_state, INT2NUM(state));
@@ -285,39 +294,10 @@ ossl_tmp_dh_callback(SSL *ssl, int is_export, int keylength)
285
294
  if (!pkey)
286
295
  return NULL;
287
296
 
288
- return EVP_PKEY_get0_DH(pkey);
297
+ return (DH *)EVP_PKEY_get0_DH(pkey);
289
298
  }
290
299
  #endif /* OPENSSL_NO_DH */
291
300
 
292
- #if !defined(OPENSSL_NO_EC) && defined(HAVE_SSL_CTX_SET_TMP_ECDH_CALLBACK)
293
- static EC_KEY *
294
- ossl_tmp_ecdh_callback(SSL *ssl, int is_export, int keylength)
295
- {
296
- VALUE rb_ssl;
297
- EVP_PKEY *pkey;
298
- struct tmp_dh_callback_args args;
299
- int state;
300
-
301
- rb_ssl = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
302
- args.ssl_obj = rb_ssl;
303
- args.id = id_tmp_ecdh_callback;
304
- args.is_export = is_export;
305
- args.keylength = keylength;
306
- args.type = EVP_PKEY_EC;
307
-
308
- pkey = (EVP_PKEY *)rb_protect((VALUE (*)(VALUE))ossl_call_tmp_dh_callback,
309
- (VALUE)&args, &state);
310
- if (state) {
311
- rb_ivar_set(rb_ssl, ID_callback_state, INT2NUM(state));
312
- return NULL;
313
- }
314
- if (!pkey)
315
- return NULL;
316
-
317
- return EVP_PKEY_get0_EC_KEY(pkey);
318
- }
319
- #endif
320
-
321
301
  static VALUE
322
302
  call_verify_certificate_identity(VALUE ctx_v)
323
303
  {
@@ -387,7 +367,7 @@ ossl_call_session_get_cb(VALUE ary)
387
367
  }
388
368
 
389
369
  static SSL_SESSION *
390
- #if (!defined(LIBRESSL_VERSION_NUMBER) ? OPENSSL_VERSION_NUMBER >= 0x10100000 : LIBRESSL_VERSION_NUMBER >= 0x2080000f)
370
+ #if defined(LIBRESSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER >= 0x10100000
391
371
  ossl_sslctx_session_get_cb(SSL *ssl, const unsigned char *buf, int len, int *copy)
392
372
  #else
393
373
  ossl_sslctx_session_get_cb(SSL *ssl, unsigned char *buf, int len, int *copy)
@@ -464,6 +444,54 @@ ossl_sslctx_session_new_cb(SSL *ssl, SSL_SESSION *sess)
464
444
  return 0;
465
445
  }
466
446
 
447
+ #if OPENSSL_VERSION_NUMBER >= 0x10101000 && !defined(LIBRESSL_VERSION_NUMBER)
448
+ /*
449
+ * It is only compatible with OpenSSL >= 1.1.1. Even if LibreSSL implements
450
+ * SSL_CTX_set_keylog_callback() from v3.4.2, it does nothing (see
451
+ * https://github.com/libressl-portable/openbsd/commit/648d39f0f035835d0653342d139883b9661e9cb6).
452
+ */
453
+
454
+ struct ossl_call_keylog_cb_args {
455
+ VALUE ssl_obj;
456
+ const char * line;
457
+ };
458
+
459
+ static VALUE
460
+ ossl_call_keylog_cb(VALUE args_v)
461
+ {
462
+ VALUE sslctx_obj, cb, line_v;
463
+ struct ossl_call_keylog_cb_args *args = (struct ossl_call_keylog_cb_args *) args_v;
464
+
465
+ sslctx_obj = rb_attr_get(args->ssl_obj, id_i_context);
466
+
467
+ cb = rb_attr_get(sslctx_obj, id_i_keylog_cb);
468
+ if (NIL_P(cb)) return Qnil;
469
+
470
+ line_v = rb_str_new_cstr(args->line);
471
+
472
+ return rb_funcall(cb, id_call, 2, args->ssl_obj, line_v);
473
+ }
474
+
475
+ static void
476
+ ossl_sslctx_keylog_cb(const SSL *ssl, const char *line)
477
+ {
478
+ VALUE ssl_obj;
479
+ struct ossl_call_keylog_cb_args args;
480
+ int state = 0;
481
+
482
+ OSSL_Debug("SSL keylog callback entered");
483
+
484
+ ssl_obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
485
+ args.ssl_obj = ssl_obj;
486
+ args.line = line;
487
+
488
+ rb_protect(ossl_call_keylog_cb, (VALUE)&args, &state);
489
+ if (state) {
490
+ rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(state));
491
+ }
492
+ }
493
+ #endif
494
+
467
495
  static VALUE
468
496
  ossl_call_session_remove_cb(VALUE ary)
469
497
  {
@@ -596,8 +624,6 @@ ssl_renegotiation_cb(const SSL *ssl)
596
624
  rb_funcallv(cb, id_call, 1, &ssl_obj);
597
625
  }
598
626
 
599
- #if !defined(OPENSSL_NO_NEXTPROTONEG) || \
600
- defined(HAVE_SSL_CTX_SET_ALPN_SELECT_CB)
601
627
  static VALUE
602
628
  ssl_npn_encode_protocol_i(RB_BLOCK_CALL_FUNC_ARGLIST(cur, encoded))
603
629
  {
@@ -616,7 +642,7 @@ static VALUE
616
642
  ssl_encode_npn_protocols(VALUE protocols)
617
643
  {
618
644
  VALUE encoded = rb_str_new(NULL, 0);
619
- rb_iterate(rb_each, protocols, ssl_npn_encode_protocol_i, encoded);
645
+ rb_block_call(protocols, id_each, 0, 0, ssl_npn_encode_protocol_i, encoded);
620
646
  return encoded;
621
647
  }
622
648
 
@@ -679,14 +705,13 @@ ssl_npn_select_cb_common(SSL *ssl, VALUE cb, const unsigned char **out,
679
705
 
680
706
  return SSL_TLSEXT_ERR_OK;
681
707
  }
682
- #endif
683
708
 
684
- #ifndef OPENSSL_NO_NEXTPROTONEG
709
+ #ifdef OSSL_USE_NEXTPROTONEG
685
710
  static int
686
711
  ssl_npn_advertise_cb(SSL *ssl, const unsigned char **out, unsigned int *outlen,
687
712
  void *arg)
688
713
  {
689
- VALUE protocols = (VALUE)arg;
714
+ VALUE protocols = rb_attr_get((VALUE)arg, id_npn_protocols_encoded);
690
715
 
691
716
  *out = (const unsigned char *) RSTRING_PTR(protocols);
692
717
  *outlen = RSTRING_LENINT(protocols);
@@ -708,7 +733,6 @@ ssl_npn_select_cb(SSL *ssl, unsigned char **out, unsigned char *outlen,
708
733
  }
709
734
  #endif
710
735
 
711
- #ifdef HAVE_SSL_CTX_SET_ALPN_SELECT_CB
712
736
  static int
713
737
  ssl_alpn_select_cb(SSL *ssl, const unsigned char **out, unsigned char *outlen,
714
738
  const unsigned char *in, unsigned int inlen, void *arg)
@@ -720,7 +744,6 @@ ssl_alpn_select_cb(SSL *ssl, const unsigned char **out, unsigned char *outlen,
720
744
 
721
745
  return ssl_npn_select_cb_common(ssl, cb, out, outlen, in, inlen);
722
746
  }
723
- #endif
724
747
 
725
748
  /* This function may serve as the entry point to support further callbacks. */
726
749
  static void
@@ -797,26 +820,6 @@ ossl_sslctx_setup(VALUE self)
797
820
  SSL_CTX_set_tmp_dh_callback(ctx, ossl_tmp_dh_callback);
798
821
  #endif
799
822
 
800
- #if !defined(OPENSSL_NO_EC)
801
- /* We added SSLContext#tmp_ecdh_callback= in Ruby 2.3.0,
802
- * but SSL_CTX_set_tmp_ecdh_callback() was removed in OpenSSL 1.1.0. */
803
- if (RTEST(rb_attr_get(self, id_i_tmp_ecdh_callback))) {
804
- # if defined(HAVE_SSL_CTX_SET_TMP_ECDH_CALLBACK)
805
- rb_warn("#tmp_ecdh_callback= is deprecated; use #ecdh_curves= instead");
806
- SSL_CTX_set_tmp_ecdh_callback(ctx, ossl_tmp_ecdh_callback);
807
- # if defined(HAVE_SSL_CTX_SET_ECDH_AUTO)
808
- /* tmp_ecdh_callback and ecdh_auto conflict; OpenSSL ignores
809
- * tmp_ecdh_callback. So disable ecdh_auto. */
810
- if (!SSL_CTX_set_ecdh_auto(ctx, 0))
811
- ossl_raise(eSSLError, "SSL_CTX_set_ecdh_auto");
812
- # endif
813
- # else
814
- ossl_raise(eSSLError, "OpenSSL does not support tmp_ecdh_callback; "
815
- "use #ecdh_curves= instead");
816
- # endif
817
- }
818
- #endif /* OPENSSL_NO_EC */
819
-
820
823
  #ifdef HAVE_SSL_CTX_SET_POST_HANDSHAKE_AUTH
821
824
  SSL_CTX_set_post_handshake_auth(ctx, 1);
822
825
  #endif
@@ -825,17 +828,7 @@ ossl_sslctx_setup(VALUE self)
825
828
  if (!NIL_P(val)) {
826
829
  X509_STORE *store = GetX509StorePtr(val); /* NO NEED TO DUP */
827
830
  SSL_CTX_set_cert_store(ctx, store);
828
- #if !defined(HAVE_X509_STORE_UP_REF)
829
- /*
830
- * WORKAROUND:
831
- * X509_STORE can count references, but
832
- * X509_STORE_free() doesn't care it.
833
- * So we won't increment it but mark it by ex_data.
834
- */
835
- SSL_CTX_set_ex_data(ctx, ossl_sslctx_ex_store_p, ctx);
836
- #else /* Fixed in OpenSSL 1.0.2; bff9ce4db38b (master), 5b4b9ce976fc (1.0.2) */
837
831
  X509_STORE_up_ref(store);
838
- #endif
839
832
  }
840
833
 
841
834
  val = rb_attr_get(self, id_i_extra_chain_cert);
@@ -886,10 +879,17 @@ ossl_sslctx_setup(VALUE self)
886
879
  ca_file = NIL_P(val) ? NULL : StringValueCStr(val);
887
880
  val = rb_attr_get(self, id_i_ca_path);
888
881
  ca_path = NIL_P(val) ? NULL : StringValueCStr(val);
889
- if(ca_file || ca_path){
890
- if (!SSL_CTX_load_verify_locations(ctx, ca_file, ca_path))
891
- rb_warning("can't set verify locations");
882
+ #ifdef HAVE_SSL_CTX_LOAD_VERIFY_FILE
883
+ if (ca_file && !SSL_CTX_load_verify_file(ctx, ca_file))
884
+ ossl_raise(eSSLError, "SSL_CTX_load_verify_file");
885
+ if (ca_path && !SSL_CTX_load_verify_dir(ctx, ca_path))
886
+ ossl_raise(eSSLError, "SSL_CTX_load_verify_dir");
887
+ #else
888
+ if (ca_file || ca_path) {
889
+ if (!SSL_CTX_load_verify_locations(ctx, ca_file, ca_path))
890
+ ossl_raise(eSSLError, "SSL_CTX_load_verify_locations");
892
891
  }
892
+ #endif
893
893
 
894
894
  val = rb_attr_get(self, id_i_verify_mode);
895
895
  verify_mode = NIL_P(val) ? SSL_VERIFY_NONE : NUM2INT(val);
@@ -903,12 +903,12 @@ ossl_sslctx_setup(VALUE self)
903
903
  val = rb_attr_get(self, id_i_verify_depth);
904
904
  if(!NIL_P(val)) SSL_CTX_set_verify_depth(ctx, NUM2INT(val));
905
905
 
906
- #ifndef OPENSSL_NO_NEXTPROTONEG
906
+ #ifdef OSSL_USE_NEXTPROTONEG
907
907
  val = rb_attr_get(self, id_i_npn_protocols);
908
908
  if (!NIL_P(val)) {
909
909
  VALUE encoded = ssl_encode_npn_protocols(val);
910
910
  rb_ivar_set(self, id_npn_protocols_encoded, encoded);
911
- SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_npn_advertise_cb, (void *)encoded);
911
+ SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_npn_advertise_cb, (void *)self);
912
912
  OSSL_Debug("SSL NPN advertise callback added");
913
913
  }
914
914
  if (RTEST(rb_attr_get(self, id_i_npn_select_cb))) {
@@ -917,7 +917,6 @@ ossl_sslctx_setup(VALUE self)
917
917
  }
918
918
  #endif
919
919
 
920
- #ifdef HAVE_SSL_CTX_SET_ALPN_SELECT_CB
921
920
  val = rb_attr_get(self, id_i_alpn_protocols);
922
921
  if (!NIL_P(val)) {
923
922
  VALUE rprotos = ssl_encode_npn_protocols(val);
@@ -932,7 +931,6 @@ ossl_sslctx_setup(VALUE self)
932
931
  SSL_CTX_set_alpn_select_cb(ctx, ssl_alpn_select_cb, (void *) self);
933
932
  OSSL_Debug("SSL ALPN select callback added");
934
933
  }
935
- #endif
936
934
 
937
935
  rb_obj_freeze(self);
938
936
 
@@ -964,6 +962,18 @@ ossl_sslctx_setup(VALUE self)
964
962
  OSSL_Debug("SSL TLSEXT servername callback added");
965
963
  }
966
964
 
965
+ #if OPENSSL_VERSION_NUMBER >= 0x10101000 && !defined(LIBRESSL_VERSION_NUMBER)
966
+ /*
967
+ * It is only compatible with OpenSSL >= 1.1.1. Even if LibreSSL implements
968
+ * SSL_CTX_set_keylog_callback() from v3.4.2, it does nothing (see
969
+ * https://github.com/libressl-portable/openbsd/commit/648d39f0f035835d0653342d139883b9661e9cb6).
970
+ */
971
+ if (RTEST(rb_attr_get(self, id_i_keylog_cb))) {
972
+ SSL_CTX_set_keylog_callback(ctx, ossl_sslctx_keylog_cb);
973
+ OSSL_Debug("SSL keylog callback added");
974
+ }
975
+ #endif
976
+
967
977
  return Qtrue;
968
978
  }
969
979
 
@@ -1012,27 +1022,13 @@ ossl_sslctx_get_ciphers(VALUE self)
1012
1022
  return ary;
1013
1023
  }
1014
1024
 
1015
- /*
1016
- * call-seq:
1017
- * ctx.ciphers = "cipher1:cipher2:..."
1018
- * ctx.ciphers = [name, ...]
1019
- * ctx.ciphers = [[name, version, bits, alg_bits], ...]
1020
- *
1021
- * Sets the list of available cipher suites for this context. Note in a server
1022
- * context some ciphers require the appropriate certificates. For example, an
1023
- * RSA cipher suite can only be chosen when an RSA certificate is available.
1024
- */
1025
1025
  static VALUE
1026
- ossl_sslctx_set_ciphers(VALUE self, VALUE v)
1026
+ build_cipher_string(VALUE v)
1027
1027
  {
1028
- SSL_CTX *ctx;
1029
1028
  VALUE str, elem;
1030
1029
  int i;
1031
1030
 
1032
- rb_check_frozen(self);
1033
- if (NIL_P(v))
1034
- return v;
1035
- else if (RB_TYPE_P(v, T_ARRAY)) {
1031
+ if (RB_TYPE_P(v, T_ARRAY)) {
1036
1032
  str = rb_str_new(0, 0);
1037
1033
  for (i = 0; i < RARRAY_LEN(v); i++) {
1038
1034
  elem = rb_ary_entry(v, i);
@@ -1046,14 +1042,113 @@ ossl_sslctx_set_ciphers(VALUE self, VALUE v)
1046
1042
  StringValue(str);
1047
1043
  }
1048
1044
 
1045
+ return str;
1046
+ }
1047
+
1048
+ /*
1049
+ * call-seq:
1050
+ * ctx.ciphers = "cipher1:cipher2:..."
1051
+ * ctx.ciphers = [name, ...]
1052
+ * ctx.ciphers = [[name, version, bits, alg_bits], ...]
1053
+ *
1054
+ * Sets the list of available cipher suites for this context. Note in a server
1055
+ * context some ciphers require the appropriate certificates. For example, an
1056
+ * RSA cipher suite can only be chosen when an RSA certificate is available.
1057
+ */
1058
+ static VALUE
1059
+ ossl_sslctx_set_ciphers(VALUE self, VALUE v)
1060
+ {
1061
+ SSL_CTX *ctx;
1062
+ VALUE str;
1063
+
1064
+ rb_check_frozen(self);
1065
+ if (NIL_P(v))
1066
+ return v;
1067
+
1068
+ str = build_cipher_string(v);
1069
+
1049
1070
  GetSSLCTX(self, ctx);
1050
- if (!SSL_CTX_set_cipher_list(ctx, StringValueCStr(str))) {
1071
+ if (!SSL_CTX_set_cipher_list(ctx, StringValueCStr(str)))
1051
1072
  ossl_raise(eSSLError, "SSL_CTX_set_cipher_list");
1052
- }
1053
1073
 
1054
1074
  return v;
1055
1075
  }
1056
1076
 
1077
+ #ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
1078
+ /*
1079
+ * call-seq:
1080
+ * ctx.ciphersuites = "cipher1:cipher2:..."
1081
+ * ctx.ciphersuites = [name, ...]
1082
+ * ctx.ciphersuites = [[name, version, bits, alg_bits], ...]
1083
+ *
1084
+ * Sets the list of available TLSv1.3 cipher suites for this context.
1085
+ */
1086
+ static VALUE
1087
+ ossl_sslctx_set_ciphersuites(VALUE self, VALUE v)
1088
+ {
1089
+ SSL_CTX *ctx;
1090
+ VALUE str;
1091
+
1092
+ rb_check_frozen(self);
1093
+ if (NIL_P(v))
1094
+ return v;
1095
+
1096
+ str = build_cipher_string(v);
1097
+
1098
+ GetSSLCTX(self, ctx);
1099
+ if (!SSL_CTX_set_ciphersuites(ctx, StringValueCStr(str)))
1100
+ ossl_raise(eSSLError, "SSL_CTX_set_ciphersuites");
1101
+
1102
+ return v;
1103
+ }
1104
+ #endif
1105
+
1106
+ #ifndef OPENSSL_NO_DH
1107
+ /*
1108
+ * call-seq:
1109
+ * ctx.tmp_dh = pkey
1110
+ *
1111
+ * Sets DH parameters used for ephemeral DH key exchange. This is relevant for
1112
+ * servers only.
1113
+ *
1114
+ * +pkey+ is an instance of OpenSSL::PKey::DH. Note that key components
1115
+ * contained in the key object, if any, are ignored. The server will always
1116
+ * generate a new key pair for each handshake.
1117
+ *
1118
+ * Added in version 3.0. See also the man page SSL_set0_tmp_dh_pkey(3).
1119
+ *
1120
+ * Example:
1121
+ * ctx = OpenSSL::SSL::SSLContext.new
1122
+ * ctx.tmp_dh = OpenSSL::DH.generate(2048)
1123
+ * svr = OpenSSL::SSL::SSLServer.new(tcp_svr, ctx)
1124
+ * Thread.new { svr.accept }
1125
+ */
1126
+ static VALUE
1127
+ ossl_sslctx_set_tmp_dh(VALUE self, VALUE arg)
1128
+ {
1129
+ SSL_CTX *ctx;
1130
+ EVP_PKEY *pkey;
1131
+
1132
+ rb_check_frozen(self);
1133
+ GetSSLCTX(self, ctx);
1134
+ pkey = GetPKeyPtr(arg);
1135
+
1136
+ if (EVP_PKEY_base_id(pkey) != EVP_PKEY_DH)
1137
+ rb_raise(eSSLError, "invalid pkey type %s (expected DH)",
1138
+ OBJ_nid2sn(EVP_PKEY_base_id(pkey)));
1139
+ #ifdef HAVE_SSL_SET0_TMP_DH_PKEY
1140
+ if (!SSL_CTX_set0_tmp_dh_pkey(ctx, pkey))
1141
+ ossl_raise(eSSLError, "SSL_CTX_set0_tmp_dh_pkey");
1142
+ EVP_PKEY_up_ref(pkey);
1143
+ #else
1144
+ if (!SSL_CTX_set_tmp_dh(ctx, EVP_PKEY_get0_DH(pkey)))
1145
+ ossl_raise(eSSLError, "SSL_CTX_set_tmp_dh");
1146
+ #endif
1147
+
1148
+ return arg;
1149
+ }
1150
+ #endif
1151
+
1057
1152
  #if !defined(OPENSSL_NO_EC)
1058
1153
  /*
1059
1154
  * call-seq:
@@ -1065,9 +1160,6 @@ ossl_sslctx_set_ciphers(VALUE self, VALUE v)
1065
1160
  * Extension. For a server, the list is used by OpenSSL to determine the set of
1066
1161
  * shared curves. OpenSSL will pick the most appropriate one from it.
1067
1162
  *
1068
- * Note that this works differently with old OpenSSL (<= 1.0.1). Only one curve
1069
- * can be set, and this has no effect for TLS clients.
1070
- *
1071
1163
  * === Example
1072
1164
  * ctx1 = OpenSSL::SSL::SSLContext.new
1073
1165
  * ctx1.ecdh_curves = "X25519:P-256:P-224"
@@ -1091,48 +1183,8 @@ ossl_sslctx_set_ecdh_curves(VALUE self, VALUE arg)
1091
1183
  GetSSLCTX(self, ctx);
1092
1184
  StringValueCStr(arg);
1093
1185
 
1094
- #if defined(HAVE_SSL_CTX_SET1_CURVES_LIST)
1095
1186
  if (!SSL_CTX_set1_curves_list(ctx, RSTRING_PTR(arg)))
1096
1187
  ossl_raise(eSSLError, NULL);
1097
- #else
1098
- /* OpenSSL does not have SSL_CTX_set1_curves_list()... Fallback to
1099
- * SSL_CTX_set_tmp_ecdh(). So only the first curve is used. */
1100
- {
1101
- VALUE curve, splitted;
1102
- EC_KEY *ec;
1103
- int nid;
1104
-
1105
- splitted = rb_str_split(arg, ":");
1106
- if (!RARRAY_LEN(splitted))
1107
- ossl_raise(eSSLError, "invalid input format");
1108
- curve = RARRAY_AREF(splitted, 0);
1109
- StringValueCStr(curve);
1110
-
1111
- /* SSL_CTX_set1_curves_list() accepts NIST names */
1112
- nid = EC_curve_nist2nid(RSTRING_PTR(curve));
1113
- if (nid == NID_undef)
1114
- nid = OBJ_txt2nid(RSTRING_PTR(curve));
1115
- if (nid == NID_undef)
1116
- ossl_raise(eSSLError, "unknown curve name");
1117
-
1118
- ec = EC_KEY_new_by_curve_name(nid);
1119
- if (!ec)
1120
- ossl_raise(eSSLError, NULL);
1121
- EC_KEY_set_asn1_flag(ec, OPENSSL_EC_NAMED_CURVE);
1122
- if (!SSL_CTX_set_tmp_ecdh(ctx, ec)) {
1123
- EC_KEY_free(ec);
1124
- ossl_raise(eSSLError, "SSL_CTX_set_tmp_ecdh");
1125
- }
1126
- EC_KEY_free(ec);
1127
- # if defined(HAVE_SSL_CTX_SET_ECDH_AUTO)
1128
- /* tmp_ecdh and ecdh_auto conflict. tmp_ecdh is ignored when ecdh_auto
1129
- * is enabled. So disable ecdh_auto. */
1130
- if (!SSL_CTX_set_ecdh_auto(ctx, 0))
1131
- ossl_raise(eSSLError, "SSL_CTX_set_ecdh_auto");
1132
- # endif
1133
- }
1134
- #endif
1135
-
1136
1188
  return arg;
1137
1189
  }
1138
1190
  #else
@@ -1223,7 +1275,7 @@ ossl_sslctx_enable_fallback_scsv(VALUE self)
1223
1275
 
1224
1276
  /*
1225
1277
  * call-seq:
1226
- * ctx.add_certificate(certiticate, pkey [, extra_certs]) -> self
1278
+ * ctx.add_certificate(certificate, pkey [, extra_certs]) -> self
1227
1279
  *
1228
1280
  * Adds a certificate to the context. _pkey_ must be a corresponding private
1229
1281
  * key with _certificate_.
@@ -1255,10 +1307,6 @@ ossl_sslctx_enable_fallback_scsv(VALUE self)
1255
1307
  * ecdsa_pkey = ...
1256
1308
  * another_ca_cert = ...
1257
1309
  * ctx.add_certificate(ecdsa_cert, ecdsa_pkey, [another_ca_cert])
1258
- *
1259
- * === Note
1260
- * OpenSSL before the version 1.0.2 could handle only one extra chain across
1261
- * all key types. Calling this method discards the chain set previously.
1262
1310
  */
1263
1311
  static VALUE
1264
1312
  ossl_sslctx_add_certificate(int argc, VALUE *argv, VALUE self)
@@ -1283,7 +1331,7 @@ ossl_sslctx_add_certificate(int argc, VALUE *argv, VALUE self)
1283
1331
  EVP_PKEY_free(pub_pkey);
1284
1332
  if (!pub_pkey)
1285
1333
  rb_raise(rb_eArgError, "certificate does not contain public key");
1286
- if (EVP_PKEY_cmp(pub_pkey, pkey) != 1)
1334
+ if (EVP_PKEY_eq(pub_pkey, pkey) != 1)
1287
1335
  rb_raise(rb_eArgError, "public key mismatch");
1288
1336
 
1289
1337
  if (argc >= 3)
@@ -1297,34 +1345,9 @@ ossl_sslctx_add_certificate(int argc, VALUE *argv, VALUE self)
1297
1345
  sk_X509_pop_free(extra_chain, X509_free);
1298
1346
  ossl_raise(eSSLError, "SSL_CTX_use_PrivateKey");
1299
1347
  }
1300
-
1301
- if (extra_chain) {
1302
- #if OPENSSL_VERSION_NUMBER >= 0x10002000 && !defined(LIBRESSL_VERSION_NUMBER)
1303
- if (!SSL_CTX_set0_chain(ctx, extra_chain)) {
1304
- sk_X509_pop_free(extra_chain, X509_free);
1305
- ossl_raise(eSSLError, "SSL_CTX_set0_chain");
1306
- }
1307
- #else
1308
- STACK_OF(X509) *orig_extra_chain;
1309
- X509 *x509_tmp;
1310
-
1311
- /* First, clear the existing chain */
1312
- SSL_CTX_get_extra_chain_certs(ctx, &orig_extra_chain);
1313
- if (orig_extra_chain && sk_X509_num(orig_extra_chain)) {
1314
- rb_warning("SSL_CTX_set0_chain() is not available; " \
1315
- "clearing previously set certificate chain");
1316
- SSL_CTX_clear_extra_chain_certs(ctx);
1317
- }
1318
- while ((x509_tmp = sk_X509_shift(extra_chain))) {
1319
- /* Transfers ownership */
1320
- if (!SSL_CTX_add_extra_chain_cert(ctx, x509_tmp)) {
1321
- X509_free(x509_tmp);
1322
- sk_X509_pop_free(extra_chain, X509_free);
1323
- ossl_raise(eSSLError, "SSL_CTX_add_extra_chain_cert");
1324
- }
1325
- }
1326
- sk_X509_free(extra_chain);
1327
- #endif
1348
+ if (extra_chain && !SSL_CTX_set0_chain(ctx, extra_chain)) {
1349
+ sk_X509_pop_free(extra_chain, X509_free);
1350
+ ossl_raise(eSSLError, "SSL_CTX_set0_chain");
1328
1351
  }
1329
1352
  return self;
1330
1353
  }
@@ -1518,12 +1541,23 @@ ossl_sslctx_flush_sessions(int argc, VALUE *argv, VALUE self)
1518
1541
  /*
1519
1542
  * SSLSocket class
1520
1543
  */
1521
- #ifndef OPENSSL_NO_SOCK
1522
1544
  static inline int
1523
1545
  ssl_started(SSL *ssl)
1524
1546
  {
1525
- /* the FD is set in ossl_ssl_setup(), called by #connect or #accept */
1526
- return SSL_get_fd(ssl) >= 0;
1547
+ /* BIO is created through ossl_ssl_setup(), called by #connect or #accept */
1548
+ return SSL_get_rbio(ssl) != NULL;
1549
+ }
1550
+
1551
+ static void
1552
+ ossl_ssl_mark(void *ptr)
1553
+ {
1554
+ SSL *ssl = ptr;
1555
+ rb_gc_mark((VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx));
1556
+
1557
+ // Note: this reference is stored as @verify_callback so we don't need to mark it.
1558
+ // However we do need to ensure GC compaction won't move it, hence why
1559
+ // we call rb_gc_mark here.
1560
+ rb_gc_mark((VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_vcb_idx));
1527
1561
  }
1528
1562
 
1529
1563
  static void
@@ -1535,9 +1569,9 @@ ossl_ssl_free(void *ssl)
1535
1569
  const rb_data_type_t ossl_ssl_type = {
1536
1570
  "OpenSSL/SSL",
1537
1571
  {
1538
- 0, ossl_ssl_free,
1572
+ ossl_ssl_mark, ossl_ssl_free,
1539
1573
  },
1540
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
1574
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
1541
1575
  };
1542
1576
 
1543
1577
  static VALUE
@@ -1546,6 +1580,29 @@ ossl_ssl_s_alloc(VALUE klass)
1546
1580
  return TypedData_Wrap_Struct(klass, &ossl_ssl_type, NULL);
1547
1581
  }
1548
1582
 
1583
+ static VALUE
1584
+ peer_ip_address(VALUE self)
1585
+ {
1586
+ VALUE remote_address = rb_funcall(rb_attr_get(self, id_i_io), rb_intern("remote_address"), 0);
1587
+
1588
+ return rb_funcall(remote_address, rb_intern("inspect_sockaddr"), 0);
1589
+ }
1590
+
1591
+ static VALUE
1592
+ fallback_peer_ip_address(VALUE self, VALUE args)
1593
+ {
1594
+ return rb_str_new_cstr("(null)");
1595
+ }
1596
+
1597
+ static VALUE
1598
+ peeraddr_ip_str(VALUE self)
1599
+ {
1600
+ VALUE rb_mErrno = rb_const_get(rb_cObject, rb_intern("Errno"));
1601
+ VALUE rb_eSystemCallError = rb_const_get(rb_mErrno, rb_intern("SystemCallError"));
1602
+
1603
+ return rb_rescue2(peer_ip_address, self, fallback_peer_ip_address, (VALUE)0, rb_eSystemCallError, NULL);
1604
+ }
1605
+
1549
1606
  /*
1550
1607
  * call-seq:
1551
1608
  * SSLSocket.new(io) => aSSLSocket
@@ -1582,6 +1639,7 @@ ossl_ssl_initialize(int argc, VALUE *argv, VALUE self)
1582
1639
 
1583
1640
  if (rb_respond_to(io, rb_intern("nonblock=")))
1584
1641
  rb_funcall(io, rb_intern("nonblock="), 1, Qtrue);
1642
+ Check_Type(io, T_FILE);
1585
1643
  rb_ivar_set(self, id_i_io, io);
1586
1644
 
1587
1645
  ssl = SSL_new(ctx);
@@ -1592,6 +1650,8 @@ ossl_ssl_initialize(int argc, VALUE *argv, VALUE self)
1592
1650
  SSL_set_ex_data(ssl, ossl_ssl_ex_ptr_idx, (void *)self);
1593
1651
  SSL_set_info_callback(ssl, ssl_info_cb);
1594
1652
  verify_cb = rb_attr_get(v_ctx, id_i_verify_callback);
1653
+ // We don't need to trigger a write barrier because it's already
1654
+ // an instance variable of this object.
1595
1655
  SSL_set_ex_data(ssl, ossl_ssl_ex_vcb_idx, (void *)verify_cb);
1596
1656
 
1597
1657
  rb_call_super(0, NULL);
@@ -1599,6 +1659,17 @@ ossl_ssl_initialize(int argc, VALUE *argv, VALUE self)
1599
1659
  return self;
1600
1660
  }
1601
1661
 
1662
+ #ifndef HAVE_RB_IO_DESCRIPTOR
1663
+ static int
1664
+ io_descriptor_fallback(VALUE io)
1665
+ {
1666
+ rb_io_t *fptr;
1667
+ GetOpenFile(io, fptr);
1668
+ return fptr->fd;
1669
+ }
1670
+ #define rb_io_descriptor io_descriptor_fallback
1671
+ #endif
1672
+
1602
1673
  static VALUE
1603
1674
  ossl_ssl_setup(VALUE self)
1604
1675
  {
@@ -1614,8 +1685,8 @@ ossl_ssl_setup(VALUE self)
1614
1685
  GetOpenFile(io, fptr);
1615
1686
  rb_io_check_readable(fptr);
1616
1687
  rb_io_check_writable(fptr);
1617
- if (!SSL_set_fd(ssl, TO_SOCKET(fptr->fd)))
1618
- ossl_raise(eSSLError, "SSL_set_fd");
1688
+ if (!SSL_set_fd(ssl, TO_SOCKET(rb_io_descriptor(io))))
1689
+ ossl_raise(eSSLError, "SSL_set_fd");
1619
1690
 
1620
1691
  return Qtrue;
1621
1692
  }
@@ -1649,70 +1720,107 @@ no_exception_p(VALUE opts)
1649
1720
  return 0;
1650
1721
  }
1651
1722
 
1723
+ // Provided by Ruby 3.2.0 and later in order to support the default IO#timeout.
1724
+ #ifndef RUBY_IO_TIMEOUT_DEFAULT
1725
+ #define RUBY_IO_TIMEOUT_DEFAULT Qnil
1726
+ #endif
1727
+
1728
+ static void
1729
+ io_wait_writable(VALUE io)
1730
+ {
1731
+ #ifdef HAVE_RB_IO_MAYBE_WAIT
1732
+ rb_io_maybe_wait_writable(errno, io, RUBY_IO_TIMEOUT_DEFAULT);
1733
+ #else
1734
+ rb_io_t *fptr;
1735
+ GetOpenFile(io, fptr);
1736
+ rb_io_wait_writable(fptr->fd);
1737
+ #endif
1738
+ }
1739
+
1740
+ static void
1741
+ io_wait_readable(VALUE io)
1742
+ {
1743
+ #ifdef HAVE_RB_IO_MAYBE_WAIT
1744
+ rb_io_maybe_wait_readable(errno, io, RUBY_IO_TIMEOUT_DEFAULT);
1745
+ #else
1746
+ rb_io_t *fptr;
1747
+ GetOpenFile(io, fptr);
1748
+ rb_io_wait_readable(fptr->fd);
1749
+ #endif
1750
+ }
1751
+
1652
1752
  static VALUE
1653
- ossl_start_ssl(VALUE self, int (*func)(), const char *funcname, VALUE opts)
1753
+ ossl_start_ssl(VALUE self, int (*func)(SSL *), const char *funcname, VALUE opts)
1654
1754
  {
1655
1755
  SSL *ssl;
1656
- rb_io_t *fptr;
1657
1756
  int ret, ret2;
1658
1757
  VALUE cb_state;
1659
1758
  int nonblock = opts != Qfalse;
1660
- #if defined(SSL_R_CERTIFICATE_VERIFY_FAILED)
1661
- unsigned long err;
1662
- #endif
1663
1759
 
1664
1760
  rb_ivar_set(self, ID_callback_state, Qnil);
1665
1761
 
1666
1762
  GetSSL(self, ssl);
1667
1763
 
1668
- GetOpenFile(rb_attr_get(self, id_i_io), fptr);
1669
- for(;;){
1670
- ret = func(ssl);
1764
+ VALUE io = rb_attr_get(self, id_i_io);
1765
+ for (;;) {
1766
+ ret = func(ssl);
1671
1767
 
1672
- cb_state = rb_attr_get(self, ID_callback_state);
1768
+ cb_state = rb_attr_get(self, ID_callback_state);
1673
1769
  if (!NIL_P(cb_state)) {
1674
- /* must cleanup OpenSSL error stack before re-raising */
1675
- ossl_clear_error();
1676
- rb_jump_tag(NUM2INT(cb_state));
1677
- }
1770
+ /* must cleanup OpenSSL error stack before re-raising */
1771
+ ossl_clear_error();
1772
+ rb_jump_tag(NUM2INT(cb_state));
1773
+ }
1678
1774
 
1679
- if (ret > 0)
1680
- break;
1775
+ if (ret > 0)
1776
+ break;
1681
1777
 
1682
- switch((ret2 = ssl_get_error(ssl, ret))){
1683
- case SSL_ERROR_WANT_WRITE:
1778
+ switch ((ret2 = ssl_get_error(ssl, ret))) {
1779
+ case SSL_ERROR_WANT_WRITE:
1684
1780
  if (no_exception_p(opts)) { return sym_wait_writable; }
1685
1781
  write_would_block(nonblock);
1686
- rb_io_wait_writable(fptr->fd);
1782
+ io_wait_writable(io);
1687
1783
  continue;
1688
- case SSL_ERROR_WANT_READ:
1784
+ case SSL_ERROR_WANT_READ:
1689
1785
  if (no_exception_p(opts)) { return sym_wait_readable; }
1690
1786
  read_would_block(nonblock);
1691
- rb_io_wait_readable(fptr->fd);
1787
+ io_wait_readable(io);
1692
1788
  continue;
1693
- case SSL_ERROR_SYSCALL:
1694
- if (errno) rb_sys_fail(funcname);
1695
- ossl_raise(eSSLError, "%s SYSCALL returned=%d errno=%d state=%s", funcname, ret2, errno, SSL_state_string_long(ssl));
1789
+ case SSL_ERROR_SYSCALL:
1790
+ #ifdef __APPLE__
1791
+ /* See ossl_ssl_write_internal() */
1792
+ if (errno == EPROTOTYPE)
1793
+ continue;
1794
+ #endif
1795
+ if (errno) rb_sys_fail(funcname);
1796
+ /* fallthrough */
1797
+ default: {
1798
+ VALUE error_append = Qnil;
1696
1799
  #if defined(SSL_R_CERTIFICATE_VERIFY_FAILED)
1697
- case SSL_ERROR_SSL:
1698
- err = ERR_peek_last_error();
1699
- if (ERR_GET_LIB(err) == ERR_LIB_SSL &&
1700
- ERR_GET_REASON(err) == SSL_R_CERTIFICATE_VERIFY_FAILED) {
1701
- const char *err_msg = ERR_reason_error_string(err),
1702
- *verify_msg = X509_verify_cert_error_string(SSL_get_verify_result(ssl));
1703
- if (!err_msg)
1704
- err_msg = "(null)";
1705
- if (!verify_msg)
1706
- verify_msg = "(null)";
1707
- ossl_clear_error(); /* let ossl_raise() not append message */
1708
- ossl_raise(eSSLError, "%s returned=%d errno=%d state=%s: %s (%s)",
1709
- funcname, ret2, errno, SSL_state_string_long(ssl),
1710
- err_msg, verify_msg);
1711
- }
1800
+ unsigned long err = ERR_peek_last_error();
1801
+ if (ERR_GET_LIB(err) == ERR_LIB_SSL &&
1802
+ ERR_GET_REASON(err) == SSL_R_CERTIFICATE_VERIFY_FAILED) {
1803
+ const char *err_msg = ERR_reason_error_string(err),
1804
+ *verify_msg = X509_verify_cert_error_string(SSL_get_verify_result(ssl));
1805
+ if (!err_msg)
1806
+ err_msg = "(null)";
1807
+ if (!verify_msg)
1808
+ verify_msg = "(null)";
1809
+ ossl_clear_error(); /* let ossl_raise() not append message */
1810
+ error_append = rb_sprintf(": %s (%s)", err_msg, verify_msg);
1811
+ }
1712
1812
  #endif
1713
- default:
1714
- ossl_raise(eSSLError, "%s returned=%d errno=%d state=%s", funcname, ret2, errno, SSL_state_string_long(ssl));
1715
- }
1813
+ ossl_raise(eSSLError,
1814
+ "%s%s returned=%d errno=%d peeraddr=%"PRIsVALUE" state=%s%"PRIsVALUE,
1815
+ funcname,
1816
+ ret2 == SSL_ERROR_SYSCALL ? " SYSCALL" : "",
1817
+ ret2,
1818
+ errno,
1819
+ peeraddr_ip_str(self),
1820
+ SSL_state_string_long(ssl),
1821
+ error_append);
1822
+ }
1823
+ }
1716
1824
  }
1717
1825
 
1718
1826
  return self;
@@ -1722,8 +1830,7 @@ ossl_start_ssl(VALUE self, int (*func)(), const char *funcname, VALUE opts)
1722
1830
  * call-seq:
1723
1831
  * ssl.connect => self
1724
1832
  *
1725
- * Initiates an SSL/TLS handshake with a server. The handshake may be started
1726
- * after unencrypted data has been sent over the socket.
1833
+ * Initiates an SSL/TLS handshake with a server.
1727
1834
  */
1728
1835
  static VALUE
1729
1836
  ossl_ssl_connect(VALUE self)
@@ -1770,8 +1877,7 @@ ossl_ssl_connect_nonblock(int argc, VALUE *argv, VALUE self)
1770
1877
  * call-seq:
1771
1878
  * ssl.accept => self
1772
1879
  *
1773
- * Waits for a SSL/TLS client to initiate a handshake. The handshake may be
1774
- * started after unencrypted data has been sent over the socket.
1880
+ * Waits for a SSL/TLS client to initiate a handshake.
1775
1881
  */
1776
1882
  static VALUE
1777
1883
  ossl_ssl_accept(VALUE self)
@@ -1818,16 +1924,18 @@ static VALUE
1818
1924
  ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
1819
1925
  {
1820
1926
  SSL *ssl;
1821
- int ilen, nread = 0;
1927
+ int ilen;
1822
1928
  VALUE len, str;
1823
- rb_io_t *fptr;
1824
- VALUE io, opts = Qnil;
1929
+ VALUE opts = Qnil;
1825
1930
 
1826
1931
  if (nonblock) {
1827
1932
  rb_scan_args(argc, argv, "11:", &len, &str, &opts);
1828
1933
  } else {
1829
1934
  rb_scan_args(argc, argv, "11", &len, &str);
1830
1935
  }
1936
+ GetSSL(self, ssl);
1937
+ if (!ssl_started(ssl))
1938
+ rb_raise(eSSLError, "SSL session is not started yet");
1831
1939
 
1832
1940
  ilen = NUM2INT(len);
1833
1941
  if (NIL_P(str))
@@ -1843,74 +1951,59 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
1843
1951
  if (ilen == 0)
1844
1952
  return str;
1845
1953
 
1846
- GetSSL(self, ssl);
1847
- io = rb_attr_get(self, id_i_io);
1848
- GetOpenFile(io, fptr);
1849
- if (ssl_started(ssl)) {
1850
- for (;;){
1851
- nread = SSL_read(ssl, RSTRING_PTR(str), ilen);
1852
- switch(ssl_get_error(ssl, nread)){
1853
- case SSL_ERROR_NONE:
1854
- goto end;
1855
- case SSL_ERROR_ZERO_RETURN:
1856
- if (no_exception_p(opts)) { return Qnil; }
1857
- rb_eof_error();
1858
- case SSL_ERROR_WANT_WRITE:
1859
- if (no_exception_p(opts)) { return sym_wait_writable; }
1954
+ VALUE io = rb_attr_get(self, id_i_io);
1955
+
1956
+ rb_str_locktmp(str);
1957
+ for (;;) {
1958
+ int nread = SSL_read(ssl, RSTRING_PTR(str), ilen);
1959
+ switch (ssl_get_error(ssl, nread)) {
1960
+ case SSL_ERROR_NONE:
1961
+ rb_str_unlocktmp(str);
1962
+ rb_str_set_len(str, nread);
1963
+ return str;
1964
+ case SSL_ERROR_ZERO_RETURN:
1965
+ rb_str_unlocktmp(str);
1966
+ if (no_exception_p(opts)) { return Qnil; }
1967
+ rb_eof_error();
1968
+ case SSL_ERROR_WANT_WRITE:
1969
+ if (nonblock) {
1970
+ rb_str_unlocktmp(str);
1971
+ if (no_exception_p(opts)) { return sym_wait_writable; }
1860
1972
  write_would_block(nonblock);
1861
- rb_io_wait_writable(fptr->fd);
1862
- continue;
1863
- case SSL_ERROR_WANT_READ:
1864
- if (no_exception_p(opts)) { return sym_wait_readable; }
1973
+ }
1974
+ io_wait_writable(io);
1975
+ continue;
1976
+ case SSL_ERROR_WANT_READ:
1977
+ if (nonblock) {
1978
+ rb_str_unlocktmp(str);
1979
+ if (no_exception_p(opts)) { return sym_wait_readable; }
1865
1980
  read_would_block(nonblock);
1866
- rb_io_wait_readable(fptr->fd);
1867
- continue;
1868
- case SSL_ERROR_SYSCALL:
1869
- if (!ERR_peek_error()) {
1870
- if (errno)
1871
- rb_sys_fail(0);
1872
- else {
1873
- /*
1874
- * The underlying BIO returned 0. This is actually a
1875
- * protocol error. But unfortunately, not all
1876
- * implementations cleanly shutdown the TLS connection
1877
- * but just shutdown/close the TCP connection. So report
1878
- * EOF for now...
1879
- */
1880
- if (no_exception_p(opts)) { return Qnil; }
1881
- rb_eof_error();
1882
- }
1883
- }
1884
- /* fall through */
1885
- default:
1886
- ossl_raise(eSSLError, "SSL_read");
1887
- }
1981
+ }
1982
+ io_wait_readable(io);
1983
+ continue;
1984
+ case SSL_ERROR_SYSCALL:
1985
+ if (!ERR_peek_error()) {
1986
+ rb_str_unlocktmp(str);
1987
+ if (errno)
1988
+ rb_sys_fail(0);
1989
+ else {
1990
+ /*
1991
+ * The underlying BIO returned 0. This is actually a
1992
+ * protocol error. But unfortunately, not all
1993
+ * implementations cleanly shutdown the TLS connection
1994
+ * but just shutdown/close the TCP connection. So report
1995
+ * EOF for now...
1996
+ */
1997
+ if (no_exception_p(opts)) { return Qnil; }
1998
+ rb_eof_error();
1999
+ }
2000
+ }
2001
+ /* fall through */
2002
+ default:
2003
+ rb_str_unlocktmp(str);
2004
+ ossl_raise(eSSLError, "SSL_read");
1888
2005
  }
1889
2006
  }
1890
- else {
1891
- ID meth = nonblock ? rb_intern("read_nonblock") : rb_intern("sysread");
1892
-
1893
- rb_warning("SSL session is not started yet.");
1894
- #if defined(RB_PASS_KEYWORDS)
1895
- if (nonblock) {
1896
- VALUE argv[3];
1897
- argv[0] = len;
1898
- argv[1] = str;
1899
- argv[2] = opts;
1900
- return rb_funcallv_kw(io, meth, 3, argv, RB_PASS_KEYWORDS);
1901
- }
1902
- #else
1903
- if (nonblock) {
1904
- return rb_funcall(io, meth, 3, len, str, opts);
1905
- }
1906
- #endif
1907
- else
1908
- return rb_funcall(io, meth, 2, len, str);
1909
- }
1910
-
1911
- end:
1912
- rb_str_set_len(str, nread);
1913
- return str;
1914
2007
  }
1915
2008
 
1916
2009
  /*
@@ -1950,67 +2043,55 @@ static VALUE
1950
2043
  ossl_ssl_write_internal(VALUE self, VALUE str, VALUE opts)
1951
2044
  {
1952
2045
  SSL *ssl;
1953
- int nwrite = 0;
1954
2046
  rb_io_t *fptr;
1955
- int nonblock = opts != Qfalse;
1956
- VALUE io;
2047
+ int num, nonblock = opts != Qfalse;
2048
+ VALUE tmp;
1957
2049
 
1958
- StringValue(str);
1959
2050
  GetSSL(self, ssl);
1960
- io = rb_attr_get(self, id_i_io);
2051
+ if (!ssl_started(ssl))
2052
+ rb_raise(eSSLError, "SSL session is not started yet");
2053
+
2054
+ tmp = rb_str_new_frozen(StringValue(str));
2055
+ VALUE io = rb_attr_get(self, id_i_io);
1961
2056
  GetOpenFile(io, fptr);
1962
- if (ssl_started(ssl)) {
1963
- for (;;){
1964
- int num = RSTRING_LENINT(str);
1965
-
1966
- /* SSL_write(3ssl) manpage states num == 0 is undefined */
1967
- if (num == 0)
1968
- goto end;
1969
-
1970
- nwrite = SSL_write(ssl, RSTRING_PTR(str), num);
1971
- switch(ssl_get_error(ssl, nwrite)){
1972
- case SSL_ERROR_NONE:
1973
- goto end;
1974
- case SSL_ERROR_WANT_WRITE:
1975
- if (no_exception_p(opts)) { return sym_wait_writable; }
1976
- write_would_block(nonblock);
1977
- rb_io_wait_writable(fptr->fd);
1978
- continue;
1979
- case SSL_ERROR_WANT_READ:
1980
- if (no_exception_p(opts)) { return sym_wait_readable; }
1981
- read_would_block(nonblock);
1982
- rb_io_wait_readable(fptr->fd);
2057
+
2058
+ /* SSL_write(3ssl) manpage states num == 0 is undefined */
2059
+ num = RSTRING_LENINT(tmp);
2060
+ if (num == 0)
2061
+ return INT2FIX(0);
2062
+
2063
+ for (;;) {
2064
+ int nwritten = SSL_write(ssl, RSTRING_PTR(tmp), num);
2065
+ switch (ssl_get_error(ssl, nwritten)) {
2066
+ case SSL_ERROR_NONE:
2067
+ return INT2NUM(nwritten);
2068
+ case SSL_ERROR_WANT_WRITE:
2069
+ if (no_exception_p(opts)) { return sym_wait_writable; }
2070
+ write_would_block(nonblock);
2071
+ io_wait_writable(io);
2072
+ continue;
2073
+ case SSL_ERROR_WANT_READ:
2074
+ if (no_exception_p(opts)) { return sym_wait_readable; }
2075
+ read_would_block(nonblock);
2076
+ io_wait_readable(io);
2077
+ continue;
2078
+ case SSL_ERROR_SYSCALL:
2079
+ #ifdef __APPLE__
2080
+ /*
2081
+ * It appears that send syscall can return EPROTOTYPE if the
2082
+ * socket is being torn down. Retry to get a proper errno to
2083
+ * make the error handling in line with the socket library.
2084
+ * [Bug #14713] https://bugs.ruby-lang.org/issues/14713
2085
+ */
2086
+ if (errno == EPROTOTYPE)
1983
2087
  continue;
1984
- case SSL_ERROR_SYSCALL:
1985
- if (errno) rb_sys_fail(0);
1986
- default:
1987
- ossl_raise(eSSLError, "SSL_write");
1988
- }
1989
- }
1990
- }
1991
- else {
1992
- ID meth = nonblock ?
1993
- rb_intern("write_nonblock") : rb_intern("syswrite");
1994
-
1995
- rb_warning("SSL session is not started yet.");
1996
- #if defined(RB_PASS_KEYWORDS)
1997
- if (nonblock) {
1998
- VALUE argv[2];
1999
- argv[0] = str;
2000
- argv[1] = opts;
2001
- return rb_funcallv_kw(io, meth, 2, argv, RB_PASS_KEYWORDS);
2002
- }
2003
- #else
2004
- if (nonblock) {
2005
- return rb_funcall(io, meth, 2, str, opts);
2006
- }
2007
2088
  #endif
2008
- else
2009
- return rb_funcall(io, meth, 1, str);
2089
+ if (errno) rb_sys_fail(0);
2090
+ /* fallthrough */
2091
+ default:
2092
+ ossl_raise(eSSLError, "SSL_write");
2093
+ }
2010
2094
  }
2011
-
2012
- end:
2013
- return INT2NUM(nwrite);
2014
2095
  }
2015
2096
 
2016
2097
  /*
@@ -2385,7 +2466,7 @@ ossl_ssl_get_client_ca_list(VALUE self)
2385
2466
  return ossl_x509name_sk2ary(ca);
2386
2467
  }
2387
2468
 
2388
- # ifndef OPENSSL_NO_NEXTPROTONEG
2469
+ # ifdef OSSL_USE_NEXTPROTONEG
2389
2470
  /*
2390
2471
  * call-seq:
2391
2472
  * ssl.npn_protocol => String | nil
@@ -2410,7 +2491,6 @@ ossl_ssl_npn_protocol(VALUE self)
2410
2491
  }
2411
2492
  # endif
2412
2493
 
2413
- # ifdef HAVE_SSL_CTX_SET_ALPN_SELECT_CB
2414
2494
  /*
2415
2495
  * call-seq:
2416
2496
  * ssl.alpn_protocol => String | nil
@@ -2433,9 +2513,50 @@ ossl_ssl_alpn_protocol(VALUE self)
2433
2513
  else
2434
2514
  return rb_str_new((const char *) out, outlen);
2435
2515
  }
2436
- # endif
2437
2516
 
2438
- # ifdef HAVE_SSL_GET_SERVER_TMP_KEY
2517
+ /*
2518
+ * call-seq:
2519
+ * session.export_keying_material(label, length) -> String
2520
+ *
2521
+ * Enables use of shared session key material in accordance with RFC 5705.
2522
+ */
2523
+ static VALUE
2524
+ ossl_ssl_export_keying_material(int argc, VALUE *argv, VALUE self)
2525
+ {
2526
+ SSL *ssl;
2527
+ VALUE str;
2528
+ VALUE label;
2529
+ VALUE length;
2530
+ VALUE context;
2531
+ unsigned char *p;
2532
+ size_t len;
2533
+ int use_ctx = 0;
2534
+ unsigned char *ctx = NULL;
2535
+ size_t ctx_len = 0;
2536
+ int ret;
2537
+
2538
+ rb_scan_args(argc, argv, "21", &label, &length, &context);
2539
+ StringValue(label);
2540
+
2541
+ GetSSL(self, ssl);
2542
+
2543
+ len = (size_t)NUM2LONG(length);
2544
+ str = rb_str_new(0, len);
2545
+ p = (unsigned char *)RSTRING_PTR(str);
2546
+ if (!NIL_P(context)) {
2547
+ use_ctx = 1;
2548
+ StringValue(context);
2549
+ ctx = (unsigned char *)RSTRING_PTR(context);
2550
+ ctx_len = RSTRING_LEN(context);
2551
+ }
2552
+ ret = SSL_export_keying_material(ssl, p, len, (char *)RSTRING_PTR(label),
2553
+ RSTRING_LENINT(label), ctx, ctx_len, use_ctx);
2554
+ if (ret == 0 || ret == -1) {
2555
+ ossl_raise(eSSLError, "SSL_export_keying_material");
2556
+ }
2557
+ return str;
2558
+ }
2559
+
2439
2560
  /*
2440
2561
  * call-seq:
2441
2562
  * ssl.tmp_key => PKey or nil
@@ -2453,11 +2574,8 @@ ossl_ssl_tmp_key(VALUE self)
2453
2574
  return Qnil;
2454
2575
  return ossl_pkey_new(key);
2455
2576
  }
2456
- # endif /* defined(HAVE_SSL_GET_SERVER_TMP_KEY) */
2457
2577
  #endif /* !defined(OPENSSL_NO_SOCK) */
2458
2578
 
2459
- #undef rb_intern
2460
- #define rb_intern(s) rb_intern_const(s)
2461
2579
  void
2462
2580
  Init_ossl_ssl(void)
2463
2581
  {
@@ -2468,8 +2586,9 @@ Init_ossl_ssl(void)
2468
2586
  rb_mWaitWritable = rb_define_module_under(rb_cIO, "WaitWritable");
2469
2587
  #endif
2470
2588
 
2471
- id_call = rb_intern("call");
2472
- ID_callback_state = rb_intern("callback_state");
2589
+ #ifndef OPENSSL_NO_SOCK
2590
+ id_call = rb_intern_const("call");
2591
+ ID_callback_state = rb_intern_const("callback_state");
2473
2592
 
2474
2593
  ossl_ssl_ex_vcb_idx = SSL_get_ex_new_index(0, (void *)"ossl_ssl_ex_vcb_idx", 0, 0, 0);
2475
2594
  if (ossl_ssl_ex_vcb_idx < 0)
@@ -2480,11 +2599,6 @@ Init_ossl_ssl(void)
2480
2599
  ossl_sslctx_ex_ptr_idx = SSL_CTX_get_ex_new_index(0, (void *)"ossl_sslctx_ex_ptr_idx", 0, 0, 0);
2481
2600
  if (ossl_sslctx_ex_ptr_idx < 0)
2482
2601
  ossl_raise(rb_eRuntimeError, "SSL_CTX_get_ex_new_index");
2483
- #if !defined(HAVE_X509_STORE_UP_REF)
2484
- ossl_sslctx_ex_store_p = SSL_CTX_get_ex_new_index(0, (void *)"ossl_sslctx_ex_store_p", 0, 0, 0);
2485
- if (ossl_sslctx_ex_store_p < 0)
2486
- ossl_raise(rb_eRuntimeError, "SSL_CTX_get_ex_new_index");
2487
- #endif
2488
2602
 
2489
2603
  /* Document-module: OpenSSL::SSL
2490
2604
  *
@@ -2495,16 +2609,6 @@ Init_ossl_ssl(void)
2495
2609
  */
2496
2610
  mSSL = rb_define_module_under(mOSSL, "SSL");
2497
2611
 
2498
- /* Document-module: OpenSSL::ExtConfig
2499
- *
2500
- * This module contains configuration information about the SSL extension,
2501
- * for example if socket support is enabled, or the host name TLS extension
2502
- * is enabled. Constants in this module will always be defined, but contain
2503
- * +true+ or +false+ values depending on the configuration of your OpenSSL
2504
- * installation.
2505
- */
2506
- mSSLExtConfig = rb_define_module_under(mOSSL, "ExtConfig");
2507
-
2508
2612
  /* Document-class: OpenSSL::SSL::SSLError
2509
2613
  *
2510
2614
  * Generic error class raised by SSLSocket and SSLContext.
@@ -2536,7 +2640,7 @@ Init_ossl_ssl(void)
2536
2640
  * The _cert_, _key_, and _extra_chain_cert_ attributes are deprecated.
2537
2641
  * It is recommended to use #add_certificate instead.
2538
2642
  */
2539
- rb_attr(cSSLContext, rb_intern("cert"), 1, 1, Qfalse);
2643
+ rb_attr(cSSLContext, rb_intern_const("cert"), 1, 1, Qfalse);
2540
2644
 
2541
2645
  /*
2542
2646
  * Context private key
@@ -2544,29 +2648,29 @@ Init_ossl_ssl(void)
2544
2648
  * The _cert_, _key_, and _extra_chain_cert_ attributes are deprecated.
2545
2649
  * It is recommended to use #add_certificate instead.
2546
2650
  */
2547
- rb_attr(cSSLContext, rb_intern("key"), 1, 1, Qfalse);
2651
+ rb_attr(cSSLContext, rb_intern_const("key"), 1, 1, Qfalse);
2548
2652
 
2549
2653
  /*
2550
2654
  * A certificate or Array of certificates that will be sent to the client.
2551
2655
  */
2552
- rb_attr(cSSLContext, rb_intern("client_ca"), 1, 1, Qfalse);
2656
+ rb_attr(cSSLContext, rb_intern_const("client_ca"), 1, 1, Qfalse);
2553
2657
 
2554
2658
  /*
2555
2659
  * The path to a file containing a PEM-format CA certificate
2556
2660
  */
2557
- rb_attr(cSSLContext, rb_intern("ca_file"), 1, 1, Qfalse);
2661
+ rb_attr(cSSLContext, rb_intern_const("ca_file"), 1, 1, Qfalse);
2558
2662
 
2559
2663
  /*
2560
2664
  * The path to a directory containing CA certificates in PEM format.
2561
2665
  *
2562
2666
  * Files are looked up by subject's X509 name's hash value.
2563
2667
  */
2564
- rb_attr(cSSLContext, rb_intern("ca_path"), 1, 1, Qfalse);
2668
+ rb_attr(cSSLContext, rb_intern_const("ca_path"), 1, 1, Qfalse);
2565
2669
 
2566
2670
  /*
2567
2671
  * Maximum session lifetime in seconds.
2568
2672
  */
2569
- rb_attr(cSSLContext, rb_intern("timeout"), 1, 1, Qfalse);
2673
+ rb_attr(cSSLContext, rb_intern_const("timeout"), 1, 1, Qfalse);
2570
2674
 
2571
2675
  /*
2572
2676
  * Session verification mode.
@@ -2579,12 +2683,12 @@ Init_ossl_ssl(void)
2579
2683
  *
2580
2684
  * See SSL_CTX_set_verify(3) for details.
2581
2685
  */
2582
- rb_attr(cSSLContext, rb_intern("verify_mode"), 1, 1, Qfalse);
2686
+ rb_attr(cSSLContext, rb_intern_const("verify_mode"), 1, 1, Qfalse);
2583
2687
 
2584
2688
  /*
2585
2689
  * Number of CA certificates to walk when verifying a certificate chain.
2586
2690
  */
2587
- rb_attr(cSSLContext, rb_intern("verify_depth"), 1, 1, Qfalse);
2691
+ rb_attr(cSSLContext, rb_intern_const("verify_depth"), 1, 1, Qfalse);
2588
2692
 
2589
2693
  /*
2590
2694
  * A callback for additional certificate verification. The callback is
@@ -2598,7 +2702,7 @@ Init_ossl_ssl(void)
2598
2702
  * If the callback returns +false+, the chain verification is immediately
2599
2703
  * stopped and a bad_certificate alert is then sent.
2600
2704
  */
2601
- rb_attr(cSSLContext, rb_intern("verify_callback"), 1, 1, Qfalse);
2705
+ rb_attr(cSSLContext, rb_intern_const("verify_callback"), 1, 1, Qfalse);
2602
2706
 
2603
2707
  /*
2604
2708
  * Whether to check the server certificate is valid for the hostname.
@@ -2606,12 +2710,12 @@ Init_ossl_ssl(void)
2606
2710
  * In order to make this work, verify_mode must be set to VERIFY_PEER and
2607
2711
  * the server hostname must be given by OpenSSL::SSL::SSLSocket#hostname=.
2608
2712
  */
2609
- rb_attr(cSSLContext, rb_intern("verify_hostname"), 1, 1, Qfalse);
2713
+ rb_attr(cSSLContext, rb_intern_const("verify_hostname"), 1, 1, Qfalse);
2610
2714
 
2611
2715
  /*
2612
2716
  * An OpenSSL::X509::Store used for certificate verification.
2613
2717
  */
2614
- rb_attr(cSSLContext, rb_intern("cert_store"), 1, 1, Qfalse);
2718
+ rb_attr(cSSLContext, rb_intern_const("cert_store"), 1, 1, Qfalse);
2615
2719
 
2616
2720
  /*
2617
2721
  * An Array of extra X509 certificates to be added to the certificate
@@ -2620,7 +2724,7 @@ Init_ossl_ssl(void)
2620
2724
  * The _cert_, _key_, and _extra_chain_cert_ attributes are deprecated.
2621
2725
  * It is recommended to use #add_certificate instead.
2622
2726
  */
2623
- rb_attr(cSSLContext, rb_intern("extra_chain_cert"), 1, 1, Qfalse);
2727
+ rb_attr(cSSLContext, rb_intern_const("extra_chain_cert"), 1, 1, Qfalse);
2624
2728
 
2625
2729
  /*
2626
2730
  * A callback invoked when a client certificate is requested by a server
@@ -2630,28 +2734,14 @@ Init_ossl_ssl(void)
2630
2734
  * containing an OpenSSL::X509::Certificate and an OpenSSL::PKey. If any
2631
2735
  * other value is returned the handshake is suspended.
2632
2736
  */
2633
- rb_attr(cSSLContext, rb_intern("client_cert_cb"), 1, 1, Qfalse);
2634
-
2635
- #if !defined(OPENSSL_NO_EC) && defined(HAVE_SSL_CTX_SET_TMP_ECDH_CALLBACK)
2636
- /*
2637
- * A callback invoked when ECDH parameters are required.
2638
- *
2639
- * The callback is invoked with the Session for the key exchange, an
2640
- * flag indicating the use of an export cipher and the keylength
2641
- * required.
2642
- *
2643
- * The callback is deprecated. This does not work with recent versions of
2644
- * OpenSSL. Use OpenSSL::SSL::SSLContext#ecdh_curves= instead.
2645
- */
2646
- rb_attr(cSSLContext, rb_intern("tmp_ecdh_callback"), 1, 1, Qfalse);
2647
- #endif
2737
+ rb_attr(cSSLContext, rb_intern_const("client_cert_cb"), 1, 1, Qfalse);
2648
2738
 
2649
2739
  /*
2650
2740
  * Sets the context in which a session can be reused. This allows
2651
2741
  * sessions for multiple applications to be distinguished, for example, by
2652
2742
  * name.
2653
2743
  */
2654
- rb_attr(cSSLContext, rb_intern("session_id_context"), 1, 1, Qfalse);
2744
+ rb_attr(cSSLContext, rb_intern_const("session_id_context"), 1, 1, Qfalse);
2655
2745
 
2656
2746
  /*
2657
2747
  * A callback invoked on a server when a session is proposed by the client
@@ -2660,7 +2750,7 @@ Init_ossl_ssl(void)
2660
2750
  * The callback is invoked with the SSLSocket and session id. The
2661
2751
  * callback may return a Session from an external cache.
2662
2752
  */
2663
- rb_attr(cSSLContext, rb_intern("session_get_cb"), 1, 1, Qfalse);
2753
+ rb_attr(cSSLContext, rb_intern_const("session_get_cb"), 1, 1, Qfalse);
2664
2754
 
2665
2755
  /*
2666
2756
  * A callback invoked when a new session was negotiated.
@@ -2668,7 +2758,7 @@ Init_ossl_ssl(void)
2668
2758
  * The callback is invoked with an SSLSocket. If +false+ is returned the
2669
2759
  * session will be removed from the internal cache.
2670
2760
  */
2671
- rb_attr(cSSLContext, rb_intern("session_new_cb"), 1, 1, Qfalse);
2761
+ rb_attr(cSSLContext, rb_intern_const("session_new_cb"), 1, 1, Qfalse);
2672
2762
 
2673
2763
  /*
2674
2764
  * A callback invoked when a session is removed from the internal cache.
@@ -2679,9 +2769,7 @@ Init_ossl_ssl(void)
2679
2769
  * multi-threaded application. The callback is called inside a global lock
2680
2770
  * and it can randomly cause deadlock on Ruby thread switching.
2681
2771
  */
2682
- rb_attr(cSSLContext, rb_intern("session_remove_cb"), 1, 1, Qfalse);
2683
-
2684
- rb_define_const(mSSLExtConfig, "HAVE_TLSEXT_HOST_NAME", Qtrue);
2772
+ rb_attr(cSSLContext, rb_intern_const("session_remove_cb"), 1, 1, Qfalse);
2685
2773
 
2686
2774
  /*
2687
2775
  * A callback invoked whenever a new handshake is initiated on an
@@ -2702,8 +2790,8 @@ Init_ossl_ssl(void)
2702
2790
  * raise RuntimeError, "Client renegotiation disabled"
2703
2791
  * end
2704
2792
  */
2705
- rb_attr(cSSLContext, rb_intern("renegotiation_cb"), 1, 1, Qfalse);
2706
- #ifndef OPENSSL_NO_NEXTPROTONEG
2793
+ rb_attr(cSSLContext, rb_intern_const("renegotiation_cb"), 1, 1, Qfalse);
2794
+ #ifdef OSSL_USE_NEXTPROTONEG
2707
2795
  /*
2708
2796
  * An Enumerable of Strings. Each String represents a protocol to be
2709
2797
  * advertised as the list of supported protocols for Next Protocol
@@ -2715,7 +2803,7 @@ Init_ossl_ssl(void)
2715
2803
  *
2716
2804
  * ctx.npn_protocols = ["http/1.1", "spdy/2"]
2717
2805
  */
2718
- rb_attr(cSSLContext, rb_intern("npn_protocols"), 1, 1, Qfalse);
2806
+ rb_attr(cSSLContext, rb_intern_const("npn_protocols"), 1, 1, Qfalse);
2719
2807
  /*
2720
2808
  * A callback invoked on the client side when the client needs to select
2721
2809
  * a protocol from the list sent by the server. Supported in OpenSSL 1.0.1
@@ -2732,10 +2820,9 @@ Init_ossl_ssl(void)
2732
2820
  * protocols.first
2733
2821
  * end
2734
2822
  */
2735
- rb_attr(cSSLContext, rb_intern("npn_select_cb"), 1, 1, Qfalse);
2823
+ rb_attr(cSSLContext, rb_intern_const("npn_select_cb"), 1, 1, Qfalse);
2736
2824
  #endif
2737
2825
 
2738
- #ifdef HAVE_SSL_CTX_SET_ALPN_SELECT_CB
2739
2826
  /*
2740
2827
  * An Enumerable of Strings. Each String represents a protocol to be
2741
2828
  * advertised as the list of supported protocols for Application-Layer
@@ -2747,7 +2834,7 @@ Init_ossl_ssl(void)
2747
2834
  *
2748
2835
  * ctx.alpn_protocols = ["http/1.1", "spdy/2", "h2"]
2749
2836
  */
2750
- rb_attr(cSSLContext, rb_intern("alpn_protocols"), 1, 1, Qfalse);
2837
+ rb_attr(cSSLContext, rb_intern_const("alpn_protocols"), 1, 1, Qfalse);
2751
2838
  /*
2752
2839
  * A callback invoked on the server side when the server needs to select
2753
2840
  * a protocol from the list sent by the client. Supported in OpenSSL 1.0.2
@@ -2764,8 +2851,30 @@ Init_ossl_ssl(void)
2764
2851
  * protocols.first
2765
2852
  * end
2766
2853
  */
2767
- rb_attr(cSSLContext, rb_intern("alpn_select_cb"), 1, 1, Qfalse);
2768
- #endif
2854
+ rb_attr(cSSLContext, rb_intern_const("alpn_select_cb"), 1, 1, Qfalse);
2855
+
2856
+ /*
2857
+ * A callback invoked when TLS key material is generated or received, in
2858
+ * order to allow applications to store this keying material for debugging
2859
+ * purposes.
2860
+ *
2861
+ * The callback is invoked with an SSLSocket and a string containing the
2862
+ * key material in the format used by NSS for its SSLKEYLOGFILE debugging
2863
+ * output.
2864
+ *
2865
+ * It is only compatible with OpenSSL >= 1.1.1. Even if LibreSSL implements
2866
+ * SSL_CTX_set_keylog_callback() from v3.4.2, it does nothing (see
2867
+ * https://github.com/libressl-portable/openbsd/commit/648d39f0f035835d0653342d139883b9661e9cb6).
2868
+ *
2869
+ * === Example
2870
+ *
2871
+ * context.keylog_cb = proc do |_sock, line|
2872
+ * File.open('ssl_keylog_file', "a") do |f|
2873
+ * f.write("#{line}\n")
2874
+ * end
2875
+ * end
2876
+ */
2877
+ rb_attr(cSSLContext, rb_intern_const("keylog_cb"), 1, 1, Qfalse);
2769
2878
 
2770
2879
  rb_define_alias(cSSLContext, "ssl_timeout", "timeout");
2771
2880
  rb_define_alias(cSSLContext, "ssl_timeout=", "timeout=");
@@ -2773,6 +2882,12 @@ Init_ossl_ssl(void)
2773
2882
  ossl_sslctx_set_minmax_proto_version, 2);
2774
2883
  rb_define_method(cSSLContext, "ciphers", ossl_sslctx_get_ciphers, 0);
2775
2884
  rb_define_method(cSSLContext, "ciphers=", ossl_sslctx_set_ciphers, 1);
2885
+ #ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
2886
+ rb_define_method(cSSLContext, "ciphersuites=", ossl_sslctx_set_ciphersuites, 1);
2887
+ #endif
2888
+ #ifndef OPENSSL_NO_DH
2889
+ rb_define_method(cSSLContext, "tmp_dh=", ossl_sslctx_set_tmp_dh, 1);
2890
+ #endif
2776
2891
  rb_define_method(cSSLContext, "ecdh_curves=", ossl_sslctx_set_ecdh_curves, 1);
2777
2892
  rb_define_method(cSSLContext, "security_level", ossl_sslctx_get_security_level, 0);
2778
2893
  rb_define_method(cSSLContext, "security_level=", ossl_sslctx_set_security_level, 1);
@@ -2846,11 +2961,6 @@ Init_ossl_ssl(void)
2846
2961
  * Document-class: OpenSSL::SSL::SSLSocket
2847
2962
  */
2848
2963
  cSSLSocket = rb_define_class_under(mSSL, "SSLSocket", rb_cObject);
2849
- #ifdef OPENSSL_NO_SOCK
2850
- rb_define_const(mSSLExtConfig, "OPENSSL_NO_SOCK", Qtrue);
2851
- rb_define_method(cSSLSocket, "initialize", rb_f_notimplement, -1);
2852
- #else
2853
- rb_define_const(mSSLExtConfig, "OPENSSL_NO_SOCK", Qfalse);
2854
2964
  rb_define_alloc_func(cSSLSocket, ossl_ssl_s_alloc);
2855
2965
  rb_define_method(cSSLSocket, "initialize", ossl_ssl_initialize, -1);
2856
2966
  rb_undef_method(cSSLSocket, "initialize_copy");
@@ -2879,16 +2989,12 @@ Init_ossl_ssl(void)
2879
2989
  rb_define_method(cSSLSocket, "hostname=", ossl_ssl_set_hostname, 1);
2880
2990
  rb_define_method(cSSLSocket, "finished_message", ossl_ssl_get_finished, 0);
2881
2991
  rb_define_method(cSSLSocket, "peer_finished_message", ossl_ssl_get_peer_finished, 0);
2882
- # ifdef HAVE_SSL_GET_SERVER_TMP_KEY
2883
2992
  rb_define_method(cSSLSocket, "tmp_key", ossl_ssl_tmp_key, 0);
2884
- # endif
2885
- # ifdef HAVE_SSL_CTX_SET_ALPN_SELECT_CB
2886
2993
  rb_define_method(cSSLSocket, "alpn_protocol", ossl_ssl_alpn_protocol, 0);
2887
- # endif
2888
- # ifndef OPENSSL_NO_NEXTPROTONEG
2994
+ rb_define_method(cSSLSocket, "export_keying_material", ossl_ssl_export_keying_material, -1);
2995
+ # ifdef OSSL_USE_NEXTPROTONEG
2889
2996
  rb_define_method(cSSLSocket, "npn_protocol", ossl_ssl_npn_protocol, 0);
2890
2997
  # endif
2891
- #endif
2892
2998
 
2893
2999
  rb_define_const(mSSL, "VERIFY_NONE", INT2NUM(SSL_VERIFY_NONE));
2894
3000
  rb_define_const(mSSL, "VERIFY_PEER", INT2NUM(SSL_VERIFY_PEER));
@@ -2896,12 +3002,23 @@ Init_ossl_ssl(void)
2896
3002
  rb_define_const(mSSL, "VERIFY_CLIENT_ONCE", INT2NUM(SSL_VERIFY_CLIENT_ONCE));
2897
3003
 
2898
3004
  rb_define_const(mSSL, "OP_ALL", ULONG2NUM(SSL_OP_ALL));
3005
+ #ifdef SSL_OP_CLEANSE_PLAINTEXT /* OpenSSL 3.0 */
3006
+ rb_define_const(mSSL, "OP_CLEANSE_PLAINTEXT", ULONG2NUM(SSL_OP_CLEANSE_PLAINTEXT));
3007
+ #endif
2899
3008
  rb_define_const(mSSL, "OP_LEGACY_SERVER_CONNECT", ULONG2NUM(SSL_OP_LEGACY_SERVER_CONNECT));
2900
- #ifdef SSL_OP_TLSEXT_PADDING /* OpenSSL 1.0.1h and OpenSSL 1.0.2 */
2901
- rb_define_const(mSSL, "OP_TLSEXT_PADDING", ULONG2NUM(SSL_OP_TLSEXT_PADDING));
3009
+ #ifdef SSL_OP_ENABLE_KTLS /* OpenSSL 3.0 */
3010
+ rb_define_const(mSSL, "OP_ENABLE_KTLS", ULONG2NUM(SSL_OP_ENABLE_KTLS));
2902
3011
  #endif
2903
- #ifdef SSL_OP_SAFARI_ECDHE_ECDSA_BUG /* OpenSSL 1.0.1f and OpenSSL 1.0.2 */
3012
+ rb_define_const(mSSL, "OP_TLSEXT_PADDING", ULONG2NUM(SSL_OP_TLSEXT_PADDING));
2904
3013
  rb_define_const(mSSL, "OP_SAFARI_ECDHE_ECDSA_BUG", ULONG2NUM(SSL_OP_SAFARI_ECDHE_ECDSA_BUG));
3014
+ #ifdef SSL_OP_IGNORE_UNEXPECTED_EOF /* OpenSSL 3.0 */
3015
+ rb_define_const(mSSL, "OP_IGNORE_UNEXPECTED_EOF", ULONG2NUM(SSL_OP_IGNORE_UNEXPECTED_EOF));
3016
+ #endif
3017
+ #ifdef SSL_OP_ALLOW_CLIENT_RENEGOTIATION /* OpenSSL 3.0 */
3018
+ rb_define_const(mSSL, "OP_ALLOW_CLIENT_RENEGOTIATION", ULONG2NUM(SSL_OP_ALLOW_CLIENT_RENEGOTIATION));
3019
+ #endif
3020
+ #ifdef SSL_OP_DISABLE_TLSEXT_CA_NAMES /* OpenSSL 3.0 */
3021
+ rb_define_const(mSSL, "OP_DISABLE_TLSEXT_CA_NAMES", ULONG2NUM(SSL_OP_DISABLE_TLSEXT_CA_NAMES));
2905
3022
  #endif
2906
3023
  #ifdef SSL_OP_ALLOW_NO_DHE_KEX /* OpenSSL 1.1.1 */
2907
3024
  rb_define_const(mSSL, "OP_ALLOW_NO_DHE_KEX", ULONG2NUM(SSL_OP_ALLOW_NO_DHE_KEX));
@@ -2914,13 +3031,15 @@ Init_ossl_ssl(void)
2914
3031
  #ifdef SSL_OP_NO_ENCRYPT_THEN_MAC /* OpenSSL 1.1.1 */
2915
3032
  rb_define_const(mSSL, "OP_NO_ENCRYPT_THEN_MAC", ULONG2NUM(SSL_OP_NO_ENCRYPT_THEN_MAC));
2916
3033
  #endif
2917
- rb_define_const(mSSL, "OP_CIPHER_SERVER_PREFERENCE", ULONG2NUM(SSL_OP_CIPHER_SERVER_PREFERENCE));
2918
- rb_define_const(mSSL, "OP_TLS_ROLLBACK_BUG", ULONG2NUM(SSL_OP_TLS_ROLLBACK_BUG));
2919
- #ifdef SSL_OP_NO_RENEGOTIATION /* OpenSSL 1.1.1 */
2920
- rb_define_const(mSSL, "OP_NO_RENEGOTIATION", ULONG2NUM(SSL_OP_NO_RENEGOTIATION));
3034
+ #ifdef SSL_OP_ENABLE_MIDDLEBOX_COMPAT /* OpenSSL 1.1.1 */
3035
+ rb_define_const(mSSL, "OP_ENABLE_MIDDLEBOX_COMPAT", ULONG2NUM(SSL_OP_ENABLE_MIDDLEBOX_COMPAT));
3036
+ #endif
3037
+ #ifdef SSL_OP_PRIORITIZE_CHACHA /* OpenSSL 1.1.1 */
3038
+ rb_define_const(mSSL, "OP_PRIORITIZE_CHACHA", ULONG2NUM(SSL_OP_PRIORITIZE_CHACHA));
3039
+ #endif
3040
+ #ifdef SSL_OP_NO_ANTI_REPLAY /* OpenSSL 1.1.1 */
3041
+ rb_define_const(mSSL, "OP_NO_ANTI_REPLAY", ULONG2NUM(SSL_OP_NO_ANTI_REPLAY));
2921
3042
  #endif
2922
- rb_define_const(mSSL, "OP_CRYPTOPRO_TLSEXT_BUG", ULONG2NUM(SSL_OP_CRYPTOPRO_TLSEXT_BUG));
2923
-
2924
3043
  rb_define_const(mSSL, "OP_NO_SSLv3", ULONG2NUM(SSL_OP_NO_SSLv3));
2925
3044
  rb_define_const(mSSL, "OP_NO_TLSv1", ULONG2NUM(SSL_OP_NO_TLSv1));
2926
3045
  rb_define_const(mSSL, "OP_NO_TLSv1_1", ULONG2NUM(SSL_OP_NO_TLSv1_1));
@@ -2928,6 +3047,12 @@ Init_ossl_ssl(void)
2928
3047
  #ifdef SSL_OP_NO_TLSv1_3 /* OpenSSL 1.1.1 */
2929
3048
  rb_define_const(mSSL, "OP_NO_TLSv1_3", ULONG2NUM(SSL_OP_NO_TLSv1_3));
2930
3049
  #endif
3050
+ rb_define_const(mSSL, "OP_CIPHER_SERVER_PREFERENCE", ULONG2NUM(SSL_OP_CIPHER_SERVER_PREFERENCE));
3051
+ rb_define_const(mSSL, "OP_TLS_ROLLBACK_BUG", ULONG2NUM(SSL_OP_TLS_ROLLBACK_BUG));
3052
+ #ifdef SSL_OP_NO_RENEGOTIATION /* OpenSSL 1.1.1 */
3053
+ rb_define_const(mSSL, "OP_NO_RENEGOTIATION", ULONG2NUM(SSL_OP_NO_RENEGOTIATION));
3054
+ #endif
3055
+ rb_define_const(mSSL, "OP_CRYPTOPRO_TLSEXT_BUG", ULONG2NUM(SSL_OP_CRYPTOPRO_TLSEXT_BUG));
2931
3056
 
2932
3057
  /* SSL_OP_* flags for DTLS */
2933
3058
  #if 0
@@ -2992,16 +3117,16 @@ Init_ossl_ssl(void)
2992
3117
  #endif
2993
3118
 
2994
3119
 
2995
- sym_exception = ID2SYM(rb_intern("exception"));
2996
- sym_wait_readable = ID2SYM(rb_intern("wait_readable"));
2997
- sym_wait_writable = ID2SYM(rb_intern("wait_writable"));
3120
+ sym_exception = ID2SYM(rb_intern_const("exception"));
3121
+ sym_wait_readable = ID2SYM(rb_intern_const("wait_readable"));
3122
+ sym_wait_writable = ID2SYM(rb_intern_const("wait_writable"));
2998
3123
 
2999
- id_tmp_dh_callback = rb_intern("tmp_dh_callback");
3000
- id_tmp_ecdh_callback = rb_intern("tmp_ecdh_callback");
3001
- id_npn_protocols_encoded = rb_intern("npn_protocols_encoded");
3124
+ id_tmp_dh_callback = rb_intern_const("tmp_dh_callback");
3125
+ id_npn_protocols_encoded = rb_intern_const("npn_protocols_encoded");
3126
+ id_each = rb_intern_const("each");
3002
3127
 
3003
3128
  #define DefIVarID(name) do \
3004
- id_i_##name = rb_intern("@"#name); while (0)
3129
+ id_i_##name = rb_intern_const("@"#name); while (0)
3005
3130
 
3006
3131
  DefIVarID(cert_store);
3007
3132
  DefIVarID(ca_file);
@@ -3015,7 +3140,6 @@ Init_ossl_ssl(void)
3015
3140
  DefIVarID(key);
3016
3141
  DefIVarID(extra_chain_cert);
3017
3142
  DefIVarID(client_cert_cb);
3018
- DefIVarID(tmp_ecdh_callback);
3019
3143
  DefIVarID(timeout);
3020
3144
  DefIVarID(session_id_context);
3021
3145
  DefIVarID(session_get_cb);
@@ -3027,8 +3151,10 @@ Init_ossl_ssl(void)
3027
3151
  DefIVarID(alpn_select_cb);
3028
3152
  DefIVarID(servername_cb);
3029
3153
  DefIVarID(verify_hostname);
3154
+ DefIVarID(keylog_cb);
3030
3155
 
3031
3156
  DefIVarID(io);
3032
3157
  DefIVarID(context);
3033
3158
  DefIVarID(hostname);
3159
+ #endif /* !defined(OPENSSL_NO_SOCK) */
3034
3160
  }