openssl 3.2.0 → 3.3.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 (69) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +180 -29
  3. data/History.md +114 -1
  4. data/README.md +11 -7
  5. data/ext/openssl/extconf.rb +7 -9
  6. data/ext/openssl/openssl_missing.c +1 -1
  7. data/ext/openssl/openssl_missing.h +1 -1
  8. data/ext/openssl/ossl.c +7 -9
  9. data/ext/openssl/ossl.h +12 -8
  10. data/ext/openssl/ossl_asn1.c +65 -261
  11. data/ext/openssl/ossl_asn1.h +1 -19
  12. data/ext/openssl/ossl_bio.c +1 -1
  13. data/ext/openssl/ossl_bio.h +1 -1
  14. data/ext/openssl/ossl_bn.c +12 -12
  15. data/ext/openssl/ossl_bn.h +1 -2
  16. data/ext/openssl/ossl_cipher.c +24 -9
  17. data/ext/openssl/ossl_cipher.h +1 -4
  18. data/ext/openssl/ossl_config.c +10 -9
  19. data/ext/openssl/ossl_config.h +1 -1
  20. data/ext/openssl/ossl_digest.c +39 -20
  21. data/ext/openssl/ossl_digest.h +1 -4
  22. data/ext/openssl/ossl_engine.c +3 -3
  23. data/ext/openssl/ossl_engine.h +1 -4
  24. data/ext/openssl/ossl_hmac.c +3 -3
  25. data/ext/openssl/ossl_hmac.h +1 -4
  26. data/ext/openssl/ossl_kdf.c +5 -5
  27. data/ext/openssl/ossl_ns_spki.c +8 -8
  28. data/ext/openssl/ossl_ns_spki.h +1 -5
  29. data/ext/openssl/ossl_ocsp.c +8 -8
  30. data/ext/openssl/ossl_ocsp.h +1 -8
  31. data/ext/openssl/ossl_pkcs12.c +54 -3
  32. data/ext/openssl/ossl_pkcs12.h +1 -4
  33. data/ext/openssl/ossl_pkcs7.c +79 -22
  34. data/ext/openssl/ossl_pkcs7.h +2 -22
  35. data/ext/openssl/ossl_pkey.c +1 -1
  36. data/ext/openssl/ossl_pkey.h +3 -14
  37. data/ext/openssl/ossl_pkey_dh.c +2 -2
  38. data/ext/openssl/ossl_pkey_dsa.c +2 -2
  39. data/ext/openssl/ossl_pkey_ec.c +6 -6
  40. data/ext/openssl/ossl_pkey_rsa.c +2 -2
  41. data/ext/openssl/ossl_provider.c +1 -1
  42. data/ext/openssl/ossl_rand.c +3 -3
  43. data/ext/openssl/ossl_rand.h +1 -4
  44. data/ext/openssl/ossl_ssl.c +71 -52
  45. data/ext/openssl/ossl_ssl.h +1 -1
  46. data/ext/openssl/ossl_ts.c +73 -15
  47. data/ext/openssl/ossl_ts.h +1 -1
  48. data/ext/openssl/ossl_x509.c +1 -1
  49. data/ext/openssl/ossl_x509.h +1 -20
  50. data/ext/openssl/ossl_x509attr.c +25 -26
  51. data/ext/openssl/ossl_x509cert.c +42 -3
  52. data/ext/openssl/ossl_x509crl.c +8 -4
  53. data/ext/openssl/ossl_x509ext.c +3 -3
  54. data/ext/openssl/ossl_x509name.c +3 -3
  55. data/ext/openssl/ossl_x509req.c +8 -4
  56. data/ext/openssl/ossl_x509revoked.c +2 -2
  57. data/ext/openssl/ossl_x509store.c +16 -11
  58. data/lib/openssl/asn1.rb +188 -0
  59. data/lib/openssl/bn.rb +1 -1
  60. data/lib/openssl/buffering.rb +24 -9
  61. data/lib/openssl/cipher.rb +1 -1
  62. data/lib/openssl/digest.rb +1 -1
  63. data/lib/openssl/marshal.rb +1 -1
  64. data/lib/openssl/ssl.rb +67 -4
  65. data/lib/openssl/version.rb +1 -1
  66. data/lib/openssl/x509.rb +6 -6
  67. data/lib/openssl.rb +2 -1
  68. metadata +6 -4
  69. /data/{LICENSE.txt → COPYING} +0 -0
@@ -5,10 +5,25 @@
5
5
  */
6
6
  /*
7
7
  * This program is licensed under the same licence as Ruby.
8
- * (See the file 'LICENCE'.)
8
+ * (See the file 'COPYING'.)
9
9
  */
10
10
  #include "ossl.h"
11
11
 
12
+ #define NewPKCS7(klass) \
13
+ TypedData_Wrap_Struct((klass), &ossl_pkcs7_type, 0)
14
+ #define SetPKCS7(obj, pkcs7) do { \
15
+ if (!(pkcs7)) { \
16
+ ossl_raise(rb_eRuntimeError, "PKCS7 wasn't initialized."); \
17
+ } \
18
+ RTYPEDDATA_DATA(obj) = (pkcs7); \
19
+ } while (0)
20
+ #define GetPKCS7(obj, pkcs7) do { \
21
+ TypedData_Get_Struct((obj), PKCS7, &ossl_pkcs7_type, (pkcs7)); \
22
+ if (!(pkcs7)) { \
23
+ ossl_raise(rb_eRuntimeError, "PKCS7 wasn't initialized."); \
24
+ } \
25
+ } while (0)
26
+
12
27
  #define NewPKCS7si(klass) \
13
28
  TypedData_Wrap_Struct((klass), &ossl_pkcs7_signer_info_type, 0)
14
29
  #define SetPKCS7si(obj, p7si) do { \
@@ -49,10 +64,10 @@
49
64
  /*
50
65
  * Classes
51
66
  */
52
- VALUE cPKCS7;
53
- VALUE cPKCS7Signer;
54
- VALUE cPKCS7Recipient;
55
- VALUE ePKCS7Error;
67
+ static VALUE cPKCS7;
68
+ static VALUE cPKCS7Signer;
69
+ static VALUE cPKCS7Recipient;
70
+ static VALUE ePKCS7Error;
56
71
 
57
72
  static void
58
73
  ossl_pkcs7_free(void *ptr)
@@ -60,7 +75,7 @@ ossl_pkcs7_free(void *ptr)
60
75
  PKCS7_free(ptr);
61
76
  }
62
77
 
63
- const rb_data_type_t ossl_pkcs7_type = {
78
+ static const rb_data_type_t ossl_pkcs7_type = {
64
79
  "OpenSSL/PKCS7",
65
80
  {
66
81
  0, ossl_pkcs7_free,
@@ -68,6 +83,20 @@ const rb_data_type_t ossl_pkcs7_type = {
68
83
  0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
69
84
  };
70
85
 
86
+ VALUE
87
+ ossl_pkcs7_new(PKCS7 *p7)
88
+ {
89
+ PKCS7 *new;
90
+ VALUE obj = NewPKCS7(cPKCS7);
91
+
92
+ new = PKCS7_dup(p7);
93
+ if (!new)
94
+ ossl_raise(ePKCS7Error, "PKCS7_dup");
95
+ SetPKCS7(obj, new);
96
+
97
+ return obj;
98
+ }
99
+
71
100
  static void
72
101
  ossl_pkcs7_signer_info_free(void *ptr)
73
102
  {
@@ -165,7 +194,13 @@ ossl_pkcs7_s_read_smime(VALUE klass, VALUE arg)
165
194
  out = NULL;
166
195
  pkcs7 = SMIME_read_PKCS7(in, &out);
167
196
  BIO_free(in);
168
- if(!pkcs7) ossl_raise(ePKCS7Error, NULL);
197
+ if (!pkcs7)
198
+ ossl_raise(ePKCS7Error, "Could not parse the PKCS7");
199
+ if (!pkcs7->d.ptr) {
200
+ PKCS7_free(pkcs7);
201
+ ossl_raise(ePKCS7Error, "No content in PKCS7");
202
+ }
203
+
169
204
  data = out ? ossl_membio2str(out) : Qnil;
170
205
  SetPKCS7(ret, pkcs7);
171
206
  ossl_pkcs7_set_data(ret, data);
@@ -255,7 +290,14 @@ ossl_pkcs7_s_sign(int argc, VALUE *argv, VALUE klass)
255
290
 
256
291
  /*
257
292
  * call-seq:
258
- * PKCS7.encrypt(certs, data, [, cipher [, flags]]) => pkcs7
293
+ * PKCS7.encrypt(certs, data, cipher, flags = 0) => pkcs7
294
+ *
295
+ * Creates a PKCS #7 enveloped-data structure.
296
+ *
297
+ * Before version 3.3.0, +cipher+ was optional and defaulted to
298
+ * <tt>"RC2-40-CBC"</tt>.
299
+ *
300
+ * See also the man page PKCS7_encrypt(3).
259
301
  */
260
302
  static VALUE
261
303
  ossl_pkcs7_s_encrypt(int argc, VALUE *argv, VALUE klass)
@@ -269,21 +311,12 @@ ossl_pkcs7_s_encrypt(int argc, VALUE *argv, VALUE klass)
269
311
  PKCS7 *p7;
270
312
 
271
313
  rb_scan_args(argc, argv, "22", &certs, &data, &cipher, &flags);
272
- if(NIL_P(cipher)){
273
- #if !defined(OPENSSL_NO_RC2)
274
- ciph = EVP_rc2_40_cbc();
275
- #elif !defined(OPENSSL_NO_DES)
276
- ciph = EVP_des_ede3_cbc();
277
- #elif !defined(OPENSSL_NO_RC2)
278
- ciph = EVP_rc2_40_cbc();
279
- #elif !defined(OPENSSL_NO_AES)
280
- ciph = EVP_EVP_aes_128_cbc();
281
- #else
282
- ossl_raise(ePKCS7Error, "Must specify cipher");
283
- #endif
284
-
314
+ if (NIL_P(cipher)) {
315
+ rb_raise(rb_eArgError,
316
+ "cipher must be specified. Before version 3.3, " \
317
+ "the default cipher was RC2-40-CBC.");
285
318
  }
286
- else ciph = ossl_evp_get_cipherbyname(cipher);
319
+ ciph = ossl_evp_get_cipherbyname(cipher);
287
320
  flg = NIL_P(flags) ? 0 : NUM2INT(flags);
288
321
  ret = NewPKCS7(cPKCS7);
289
322
  in = ossl_obj2bio(&data);
@@ -346,6 +379,10 @@ ossl_pkcs7_initialize(int argc, VALUE *argv, VALUE self)
346
379
  BIO_free(in);
347
380
  if (!p7)
348
381
  ossl_raise(rb_eArgError, "Could not parse the PKCS7");
382
+ if (!p7->d.ptr) {
383
+ PKCS7_free(p7);
384
+ ossl_raise(rb_eArgError, "No content in PKCS7");
385
+ }
349
386
 
350
387
  RTYPEDDATA_DATA(self) = p7;
351
388
  PKCS7_free(p7_orig);
@@ -841,6 +878,25 @@ ossl_pkcs7_to_der(VALUE self)
841
878
  return str;
842
879
  }
843
880
 
881
+ static VALUE
882
+ ossl_pkcs7_to_text(VALUE self)
883
+ {
884
+ PKCS7 *pkcs7;
885
+ BIO *out;
886
+ VALUE str;
887
+
888
+ GetPKCS7(self, pkcs7);
889
+ if(!(out = BIO_new(BIO_s_mem())))
890
+ ossl_raise(ePKCS7Error, NULL);
891
+ if(!PKCS7_print_ctx(out, pkcs7, 0, NULL)) {
892
+ BIO_free(out);
893
+ ossl_raise(ePKCS7Error, NULL);
894
+ }
895
+ str = ossl_membio2str(out);
896
+
897
+ return str;
898
+ }
899
+
844
900
  static VALUE
845
901
  ossl_pkcs7_to_pem(VALUE self)
846
902
  {
@@ -1050,6 +1106,7 @@ Init_ossl_pkcs7(void)
1050
1106
  rb_define_method(cPKCS7, "to_pem", ossl_pkcs7_to_pem, 0);
1051
1107
  rb_define_alias(cPKCS7, "to_s", "to_pem");
1052
1108
  rb_define_method(cPKCS7, "to_der", ossl_pkcs7_to_der, 0);
1109
+ rb_define_method(cPKCS7, "to_text", ossl_pkcs7_to_text, 0);
1053
1110
 
1054
1111
  cPKCS7Signer = rb_define_class_under(cPKCS7, "SignerInfo", rb_cObject);
1055
1112
  rb_define_const(cPKCS7, "Signer", cPKCS7Signer);
@@ -5,32 +5,12 @@
5
5
  */
6
6
  /*
7
7
  * This program is licensed under the same licence as Ruby.
8
- * (See the file 'LICENCE'.)
8
+ * (See the file 'COPYING'.)
9
9
  */
10
10
  #if !defined(_OSSL_PKCS7_H_)
11
11
  #define _OSSL_PKCS7_H_
12
12
 
13
- #define NewPKCS7(klass) \
14
- TypedData_Wrap_Struct((klass), &ossl_pkcs7_type, 0)
15
- #define SetPKCS7(obj, pkcs7) do { \
16
- if (!(pkcs7)) { \
17
- ossl_raise(rb_eRuntimeError, "PKCS7 wasn't initialized."); \
18
- } \
19
- RTYPEDDATA_DATA(obj) = (pkcs7); \
20
- } while (0)
21
- #define GetPKCS7(obj, pkcs7) do { \
22
- TypedData_Get_Struct((obj), PKCS7, &ossl_pkcs7_type, (pkcs7)); \
23
- if (!(pkcs7)) { \
24
- ossl_raise(rb_eRuntimeError, "PKCS7 wasn't initialized."); \
25
- } \
26
- } while (0)
27
-
28
- extern const rb_data_type_t ossl_pkcs7_type;
29
- extern VALUE cPKCS7;
30
- extern VALUE cPKCS7Signer;
31
- extern VALUE cPKCS7Recipient;
32
- extern VALUE ePKCS7Error;
33
-
13
+ VALUE ossl_pkcs7_new(PKCS7 *p7);
34
14
  void Init_ossl_pkcs7(void);
35
15
 
36
16
  #endif /* _OSSL_PKCS7_H_ */
@@ -5,7 +5,7 @@
5
5
  */
6
6
  /*
7
7
  * This program is licensed under the same licence as Ruby.
8
- * (See the file 'LICENCE'.)
8
+ * (See the file 'COPYING'.)
9
9
  */
10
10
  #include "ossl.h"
11
11
 
@@ -5,7 +5,7 @@
5
5
  */
6
6
  /*
7
7
  * This program is licensed under the same licence as Ruby.
8
- * (See the file 'LICENCE'.)
8
+ * (See the file 'COPYING'.)
9
9
  */
10
10
  #if !defined(OSSL_PKEY_H)
11
11
  #define OSSL_PKEY_H
@@ -53,35 +53,24 @@ void Init_ossl_pkey(void);
53
53
  * RSA
54
54
  */
55
55
  extern VALUE cRSA;
56
- extern VALUE eRSAError;
57
-
58
56
  void Init_ossl_rsa(void);
59
57
 
60
58
  /*
61
59
  * DSA
62
60
  */
63
61
  extern VALUE cDSA;
64
- extern VALUE eDSAError;
65
-
66
62
  void Init_ossl_dsa(void);
67
63
 
68
64
  /*
69
65
  * DH
70
66
  */
71
67
  extern VALUE cDH;
72
- extern VALUE eDHError;
73
-
74
68
  void Init_ossl_dh(void);
75
69
 
76
70
  /*
77
71
  * EC
78
72
  */
79
73
  extern VALUE cEC;
80
- extern VALUE eECError;
81
- extern VALUE cEC_GROUP;
82
- extern VALUE eEC_GROUP;
83
- extern VALUE cEC_POINT;
84
- extern VALUE eEC_POINT;
85
74
  VALUE ossl_ec_new(EVP_PKEY *);
86
75
  void Init_ossl_ec(void);
87
76
 
@@ -136,7 +125,7 @@ static VALUE ossl_##_keytype##_set_##_group(VALUE self, VALUE v1, VALUE v2, VALU
136
125
  BN_clear_free(bn1); \
137
126
  BN_clear_free(bn2); \
138
127
  BN_clear_free(bn3); \
139
- ossl_raise(eBNError, NULL); \
128
+ ossl_raise(ePKeyError, "BN_dup"); \
140
129
  } \
141
130
  \
142
131
  if (!_type##_set0_##_group(obj, bn1, bn2, bn3)) { \
@@ -164,7 +153,7 @@ static VALUE ossl_##_keytype##_set_##_group(VALUE self, VALUE v1, VALUE v2) \
164
153
  (orig_bn2 && !(bn2 = BN_dup(orig_bn2)))) { \
165
154
  BN_clear_free(bn1); \
166
155
  BN_clear_free(bn2); \
167
- ossl_raise(eBNError, NULL); \
156
+ ossl_raise(ePKeyError, "BN_dup"); \
168
157
  } \
169
158
  \
170
159
  if (!_type##_set0_##_group(obj, bn1, bn2)) { \
@@ -5,7 +5,7 @@
5
5
  */
6
6
  /*
7
7
  * This program is licensed under the same licence as Ruby.
8
- * (See the file 'LICENCE'.)
8
+ * (See the file 'COPYING'.)
9
9
  */
10
10
  #include "ossl.h"
11
11
 
@@ -27,7 +27,7 @@
27
27
  * Classes
28
28
  */
29
29
  VALUE cDH;
30
- VALUE eDHError;
30
+ static VALUE eDHError;
31
31
 
32
32
  /*
33
33
  * Private
@@ -5,7 +5,7 @@
5
5
  */
6
6
  /*
7
7
  * This program is licensed under the same licence as Ruby.
8
- * (See the file 'LICENCE'.)
8
+ * (See the file 'COPYING'.)
9
9
  */
10
10
  #include "ossl.h"
11
11
 
@@ -41,7 +41,7 @@ DSA_PRIVATE(VALUE obj, OSSL_3_const DSA *dsa)
41
41
  * Classes
42
42
  */
43
43
  VALUE cDSA;
44
- VALUE eDSAError;
44
+ static VALUE eDSAError;
45
45
 
46
46
  /*
47
47
  * Private
@@ -41,11 +41,11 @@ static const rb_data_type_t ossl_ec_point_type;
41
41
  } while (0)
42
42
 
43
43
  VALUE cEC;
44
- VALUE eECError;
45
- VALUE cEC_GROUP;
46
- VALUE eEC_GROUP;
47
- VALUE cEC_POINT;
48
- VALUE eEC_POINT;
44
+ static VALUE eECError;
45
+ static VALUE cEC_GROUP;
46
+ static VALUE eEC_GROUP;
47
+ static VALUE cEC_POINT;
48
+ static VALUE eEC_POINT;
49
49
 
50
50
  static ID s_GFp, s_GF2m;
51
51
 
@@ -174,7 +174,7 @@ static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self)
174
174
  type = EVP_PKEY_base_id(pkey);
175
175
  if (type != EVP_PKEY_EC) {
176
176
  EVP_PKEY_free(pkey);
177
- rb_raise(eDSAError, "incorrect pkey type: %s", OBJ_nid2sn(type));
177
+ rb_raise(eECError, "incorrect pkey type: %s", OBJ_nid2sn(type));
178
178
  }
179
179
  RTYPEDDATA_DATA(self) = pkey;
180
180
  return self;
@@ -5,7 +5,7 @@
5
5
  */
6
6
  /*
7
7
  * This program is licensed under the same licence as Ruby.
8
- * (See the file 'LICENCE'.)
8
+ * (See the file 'COPYING'.)
9
9
  */
10
10
  #include "ossl.h"
11
11
 
@@ -42,7 +42,7 @@ RSA_PRIVATE(VALUE obj, OSSL_3_const RSA *rsa)
42
42
  * Classes
43
43
  */
44
44
  VALUE cRSA;
45
- VALUE eRSAError;
45
+ static VALUE eRSAError;
46
46
 
47
47
  /*
48
48
  * Private
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * This program is licensed under the same licence as Ruby.
3
- * (See the file 'LICENCE'.)
3
+ * (See the file 'COPYING'.)
4
4
  */
5
5
  #include "ossl.h"
6
6
 
@@ -5,12 +5,12 @@
5
5
  * All rights reserved.
6
6
  *
7
7
  * This program is licensed under the same licence as Ruby.
8
- * (See the file 'LICENCE'.)
8
+ * (See the file 'COPYING'.)
9
9
  */
10
10
  #include "ossl.h"
11
11
 
12
- VALUE mRandom;
13
- VALUE eRandomError;
12
+ static VALUE mRandom;
13
+ static VALUE eRandomError;
14
14
 
15
15
  /*
16
16
  * call-seq:
@@ -5,14 +5,11 @@
5
5
  */
6
6
  /*
7
7
  * This program is licensed under the same licence as Ruby.
8
- * (See the file 'LICENCE'.)
8
+ * (See the file 'COPYING'.)
9
9
  */
10
10
  #if !defined(_OSSL_RAND_H_)
11
11
  #define _OSSL_RAND_H_
12
12
 
13
- extern VALUE mRandom;
14
- extern VALUE eRandomError;
15
-
16
13
  void Init_ossl_rand(void);
17
14
 
18
15
  #endif /* _OSSL_RAND_H_ */
@@ -7,7 +7,7 @@
7
7
  */
8
8
  /*
9
9
  * This program is licensed under the same licence as Ruby.
10
- * (See the file 'LICENCE'.)
10
+ * (See the file 'COPYING'.)
11
11
  */
12
12
  #include "ossl.h"
13
13
 
@@ -35,7 +35,7 @@
35
35
 
36
36
  VALUE mSSL;
37
37
  static VALUE eSSLError;
38
- VALUE cSSLContext;
38
+ static VALUE cSSLContext;
39
39
  VALUE cSSLSocket;
40
40
 
41
41
  static VALUE eSSLErrorWaitReadable;
@@ -55,7 +55,6 @@ static ID id_i_cert_store, id_i_ca_file, id_i_ca_path, id_i_verify_mode,
55
55
  id_i_verify_hostname, id_i_keylog_cb;
56
56
  static ID id_i_io, id_i_context, id_i_hostname;
57
57
 
58
- static int ossl_ssl_ex_vcb_idx;
59
58
  static int ossl_ssl_ex_ptr_idx;
60
59
  static int ossl_sslctx_ex_ptr_idx;
61
60
 
@@ -327,9 +326,9 @@ ossl_ssl_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
327
326
  int status;
328
327
 
329
328
  ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
330
- cb = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_vcb_idx);
331
329
  ssl_obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
332
330
  sslctx_obj = rb_attr_get(ssl_obj, id_i_context);
331
+ cb = rb_attr_get(sslctx_obj, id_i_verify_callback);
333
332
  verify_hostname = rb_attr_get(sslctx_obj, id_i_verify_hostname);
334
333
 
335
334
  if (preverify_ok && RTEST(verify_hostname) && !SSL_is_server(ssl) &&
@@ -558,52 +557,42 @@ ossl_sslctx_add_extra_chain_cert_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, arg))
558
557
  static VALUE ossl_sslctx_setup(VALUE self);
559
558
 
560
559
  static VALUE
561
- ossl_call_servername_cb(VALUE ary)
560
+ ossl_call_servername_cb(VALUE arg)
562
561
  {
563
- VALUE ssl_obj, sslctx_obj, cb, ret_obj;
562
+ SSL *ssl = (void *)arg;
563
+ const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
564
+ if (!servername)
565
+ return Qnil;
564
566
 
565
- Check_Type(ary, T_ARRAY);
566
- ssl_obj = rb_ary_entry(ary, 0);
567
+ VALUE ssl_obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
568
+ VALUE sslctx_obj = rb_attr_get(ssl_obj, id_i_context);
569
+ VALUE cb = rb_attr_get(sslctx_obj, id_i_servername_cb);
570
+ VALUE ary = rb_assoc_new(ssl_obj, rb_str_new_cstr(servername));
567
571
 
568
- sslctx_obj = rb_attr_get(ssl_obj, id_i_context);
569
- cb = rb_attr_get(sslctx_obj, id_i_servername_cb);
570
- if (NIL_P(cb)) return Qnil;
571
-
572
- ret_obj = rb_funcallv(cb, id_call, 1, &ary);
572
+ VALUE ret_obj = rb_funcallv(cb, id_call, 1, &ary);
573
573
  if (rb_obj_is_kind_of(ret_obj, cSSLContext)) {
574
- SSL *ssl;
575
574
  SSL_CTX *ctx2;
576
-
577
575
  ossl_sslctx_setup(ret_obj);
578
- GetSSL(ssl_obj, ssl);
579
576
  GetSSLCTX(ret_obj, ctx2);
580
- SSL_set_SSL_CTX(ssl, ctx2);
577
+ if (!SSL_set_SSL_CTX(ssl, ctx2))
578
+ ossl_raise(eSSLError, "SSL_set_SSL_CTX");
581
579
  rb_ivar_set(ssl_obj, id_i_context, ret_obj);
582
580
  } else if (!NIL_P(ret_obj)) {
583
581
  ossl_raise(rb_eArgError, "servername_cb must return an "
584
582
  "OpenSSL::SSL::SSLContext object or nil");
585
583
  }
586
584
 
587
- return ret_obj;
585
+ return Qnil;
588
586
  }
589
587
 
590
588
  static int
591
589
  ssl_servername_cb(SSL *ssl, int *ad, void *arg)
592
590
  {
593
- VALUE ary, ssl_obj;
594
- int state = 0;
595
- const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
596
-
597
- if (!servername)
598
- return SSL_TLSEXT_ERR_OK;
599
-
600
- ssl_obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
601
- ary = rb_ary_new2(2);
602
- rb_ary_push(ary, ssl_obj);
603
- rb_ary_push(ary, rb_str_new2(servername));
591
+ int state;
604
592
 
605
- rb_protect(ossl_call_servername_cb, ary, &state);
593
+ rb_protect(ossl_call_servername_cb, (VALUE)ssl, &state);
606
594
  if (state) {
595
+ VALUE ssl_obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
607
596
  rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(state));
608
597
  return SSL_TLSEXT_ERR_ALERT_FATAL;
609
598
  }
@@ -757,7 +746,10 @@ ssl_info_cb(const SSL *ssl, int where, int val)
757
746
  }
758
747
 
759
748
  /*
760
- * Gets various OpenSSL options.
749
+ * call-seq:
750
+ * ctx.options -> integer
751
+ *
752
+ * Gets various \OpenSSL options.
761
753
  */
762
754
  static VALUE
763
755
  ossl_sslctx_get_options(VALUE self)
@@ -772,7 +764,17 @@ ossl_sslctx_get_options(VALUE self)
772
764
  }
773
765
 
774
766
  /*
775
- * Sets various OpenSSL options.
767
+ * call-seq:
768
+ * ctx.options = integer
769
+ *
770
+ * Sets various \OpenSSL options. The options are a bit field and can be
771
+ * combined with the bitwise OR operator (<tt>|</tt>). Available options are
772
+ * defined as constants in OpenSSL::SSL that begin with +OP_+.
773
+ *
774
+ * For backwards compatibility, passing +nil+ has the same effect as passing
775
+ * OpenSSL::SSL::OP_ALL.
776
+ *
777
+ * See also man page SSL_CTX_set_options(3).
776
778
  */
777
779
  static VALUE
778
780
  ossl_sslctx_set_options(VALUE self, VALUE options)
@@ -1553,11 +1555,6 @@ ossl_ssl_mark(void *ptr)
1553
1555
  {
1554
1556
  SSL *ssl = ptr;
1555
1557
  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));
1561
1558
  }
1562
1559
 
1563
1560
  static void
@@ -1622,7 +1619,7 @@ peeraddr_ip_str(VALUE self)
1622
1619
  static VALUE
1623
1620
  ossl_ssl_initialize(int argc, VALUE *argv, VALUE self)
1624
1621
  {
1625
- VALUE io, v_ctx, verify_cb;
1622
+ VALUE io, v_ctx;
1626
1623
  SSL *ssl;
1627
1624
  SSL_CTX *ctx;
1628
1625
 
@@ -1649,10 +1646,6 @@ ossl_ssl_initialize(int argc, VALUE *argv, VALUE self)
1649
1646
 
1650
1647
  SSL_set_ex_data(ssl, ossl_ssl_ex_ptr_idx, (void *)self);
1651
1648
  SSL_set_info_callback(ssl, ssl_info_cb);
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.
1655
- SSL_set_ex_data(ssl, ossl_ssl_ex_vcb_idx, (void *)verify_cb);
1656
1649
 
1657
1650
  rb_call_super(0, NULL);
1658
1651
 
@@ -1725,11 +1718,20 @@ no_exception_p(VALUE opts)
1725
1718
  #define RUBY_IO_TIMEOUT_DEFAULT Qnil
1726
1719
  #endif
1727
1720
 
1721
+ #ifdef HAVE_RB_IO_TIMEOUT
1722
+ #define IO_TIMEOUT_ERROR rb_eIOTimeoutError
1723
+ #else
1724
+ #define IO_TIMEOUT_ERROR rb_eIOError
1725
+ #endif
1726
+
1727
+
1728
1728
  static void
1729
1729
  io_wait_writable(VALUE io)
1730
1730
  {
1731
1731
  #ifdef HAVE_RB_IO_MAYBE_WAIT
1732
- rb_io_maybe_wait_writable(errno, io, RUBY_IO_TIMEOUT_DEFAULT);
1732
+ if (!rb_io_maybe_wait_writable(errno, io, RUBY_IO_TIMEOUT_DEFAULT)) {
1733
+ rb_raise(IO_TIMEOUT_ERROR, "Timed out while waiting to become writable!");
1734
+ }
1733
1735
  #else
1734
1736
  rb_io_t *fptr;
1735
1737
  GetOpenFile(io, fptr);
@@ -1741,7 +1743,9 @@ static void
1741
1743
  io_wait_readable(VALUE io)
1742
1744
  {
1743
1745
  #ifdef HAVE_RB_IO_MAYBE_WAIT
1744
- rb_io_maybe_wait_readable(errno, io, RUBY_IO_TIMEOUT_DEFAULT);
1746
+ if (!rb_io_maybe_wait_readable(errno, io, RUBY_IO_TIMEOUT_DEFAULT)) {
1747
+ rb_raise(IO_TIMEOUT_ERROR, "Timed out while waiting to become readable!");
1748
+ }
1745
1749
  #else
1746
1750
  rb_io_t *fptr;
1747
1751
  GetOpenFile(io, fptr);
@@ -1925,7 +1929,7 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
1925
1929
  {
1926
1930
  SSL *ssl;
1927
1931
  int ilen;
1928
- VALUE len, str;
1932
+ VALUE len, str, cb_state;
1929
1933
  VALUE opts = Qnil;
1930
1934
 
1931
1935
  if (nonblock) {
@@ -1947,15 +1951,25 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
1947
1951
  else
1948
1952
  rb_str_modify_expand(str, ilen - RSTRING_LEN(str));
1949
1953
  }
1950
- rb_str_set_len(str, 0);
1951
- if (ilen == 0)
1952
- return str;
1954
+
1955
+ if (ilen == 0) {
1956
+ rb_str_set_len(str, 0);
1957
+ return str;
1958
+ }
1953
1959
 
1954
1960
  VALUE io = rb_attr_get(self, id_i_io);
1955
1961
 
1956
1962
  rb_str_locktmp(str);
1957
1963
  for (;;) {
1958
1964
  int nread = SSL_read(ssl, RSTRING_PTR(str), ilen);
1965
+
1966
+ cb_state = rb_attr_get(self, ID_callback_state);
1967
+ if (!NIL_P(cb_state)) {
1968
+ rb_ivar_set(self, ID_callback_state, Qnil);
1969
+ ossl_clear_error();
1970
+ rb_jump_tag(NUM2INT(cb_state));
1971
+ }
1972
+
1959
1973
  switch (ssl_get_error(ssl, nread)) {
1960
1974
  case SSL_ERROR_NONE:
1961
1975
  rb_str_unlocktmp(str);
@@ -2045,7 +2059,7 @@ ossl_ssl_write_internal(VALUE self, VALUE str, VALUE opts)
2045
2059
  SSL *ssl;
2046
2060
  rb_io_t *fptr;
2047
2061
  int num, nonblock = opts != Qfalse;
2048
- VALUE tmp;
2062
+ VALUE tmp, cb_state;
2049
2063
 
2050
2064
  GetSSL(self, ssl);
2051
2065
  if (!ssl_started(ssl))
@@ -2062,6 +2076,14 @@ ossl_ssl_write_internal(VALUE self, VALUE str, VALUE opts)
2062
2076
 
2063
2077
  for (;;) {
2064
2078
  int nwritten = SSL_write(ssl, RSTRING_PTR(tmp), num);
2079
+
2080
+ cb_state = rb_attr_get(self, ID_callback_state);
2081
+ if (!NIL_P(cb_state)) {
2082
+ rb_ivar_set(self, ID_callback_state, Qnil);
2083
+ ossl_clear_error();
2084
+ rb_jump_tag(NUM2INT(cb_state));
2085
+ }
2086
+
2065
2087
  switch (ssl_get_error(ssl, nwritten)) {
2066
2088
  case SSL_ERROR_NONE:
2067
2089
  return INT2NUM(nwritten);
@@ -2590,9 +2612,6 @@ Init_ossl_ssl(void)
2590
2612
  id_call = rb_intern_const("call");
2591
2613
  ID_callback_state = rb_intern_const("callback_state");
2592
2614
 
2593
- ossl_ssl_ex_vcb_idx = SSL_get_ex_new_index(0, (void *)"ossl_ssl_ex_vcb_idx", 0, 0, 0);
2594
- if (ossl_ssl_ex_vcb_idx < 0)
2595
- ossl_raise(rb_eRuntimeError, "SSL_get_ex_new_index");
2596
2615
  ossl_ssl_ex_ptr_idx = SSL_get_ex_new_index(0, (void *)"ossl_ssl_ex_ptr_idx", 0, 0, 0);
2597
2616
  if (ossl_ssl_ex_ptr_idx < 0)
2598
2617
  ossl_raise(rb_eRuntimeError, "SSL_get_ex_new_index");
@@ -5,7 +5,7 @@
5
5
  */
6
6
  /*
7
7
  * This program is licensed under the same licence as Ruby.
8
- * (See the file 'LICENCE'.)
8
+ * (See the file 'COPYING'.)
9
9
  */
10
10
  #if !defined(_OSSL_SSL_H_)
11
11
  #define _OSSL_SSL_H_