rubysl-openssl 2.10 → 2.11

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 (55) hide show
  1. checksums.yaml +5 -5
  2. data/ext/rubysl/openssl/deprecation.rb +7 -3
  3. data/ext/rubysl/openssl/extconf.rb +148 -103
  4. data/ext/rubysl/openssl/openssl_missing.c +94 -275
  5. data/ext/rubysl/openssl/openssl_missing.h +167 -98
  6. data/ext/rubysl/openssl/ossl.c +266 -212
  7. data/ext/rubysl/openssl/ossl.h +27 -89
  8. data/ext/rubysl/openssl/ossl_asn1.c +157 -221
  9. data/ext/rubysl/openssl/ossl_asn1.h +11 -3
  10. data/ext/rubysl/openssl/ossl_bio.c +10 -40
  11. data/ext/rubysl/openssl/ossl_bio.h +1 -2
  12. data/ext/rubysl/openssl/ossl_bn.c +144 -100
  13. data/ext/rubysl/openssl/ossl_bn.h +3 -1
  14. data/ext/rubysl/openssl/ossl_cipher.c +270 -195
  15. data/ext/rubysl/openssl/ossl_config.c +7 -1
  16. data/ext/rubysl/openssl/ossl_config.h +0 -1
  17. data/ext/rubysl/openssl/ossl_digest.c +40 -29
  18. data/ext/rubysl/openssl/ossl_engine.c +23 -62
  19. data/ext/rubysl/openssl/ossl_hmac.c +82 -55
  20. data/ext/rubysl/openssl/ossl_ns_spki.c +22 -22
  21. data/ext/rubysl/openssl/ossl_ocsp.c +894 -144
  22. data/ext/rubysl/openssl/ossl_ocsp.h +1 -1
  23. data/ext/rubysl/openssl/ossl_pkcs12.c +47 -19
  24. data/ext/rubysl/openssl/ossl_pkcs5.c +7 -15
  25. data/ext/rubysl/openssl/ossl_pkcs7.c +38 -15
  26. data/ext/rubysl/openssl/ossl_pkey.c +151 -99
  27. data/ext/rubysl/openssl/ossl_pkey.h +123 -29
  28. data/ext/rubysl/openssl/ossl_pkey_dh.c +143 -92
  29. data/ext/rubysl/openssl/ossl_pkey_dsa.c +149 -104
  30. data/ext/rubysl/openssl/ossl_pkey_ec.c +646 -524
  31. data/ext/rubysl/openssl/ossl_pkey_rsa.c +180 -121
  32. data/ext/rubysl/openssl/ossl_rand.c +25 -21
  33. data/ext/rubysl/openssl/ossl_ssl.c +795 -413
  34. data/ext/rubysl/openssl/ossl_ssl.h +3 -0
  35. data/ext/rubysl/openssl/ossl_ssl_session.c +83 -77
  36. data/ext/rubysl/openssl/ossl_version.h +1 -1
  37. data/ext/rubysl/openssl/ossl_x509.c +92 -8
  38. data/ext/rubysl/openssl/ossl_x509.h +14 -5
  39. data/ext/rubysl/openssl/ossl_x509attr.c +77 -41
  40. data/ext/rubysl/openssl/ossl_x509cert.c +45 -46
  41. data/ext/rubysl/openssl/ossl_x509crl.c +51 -57
  42. data/ext/rubysl/openssl/ossl_x509ext.c +39 -33
  43. data/ext/rubysl/openssl/ossl_x509name.c +68 -45
  44. data/ext/rubysl/openssl/ossl_x509req.c +32 -38
  45. data/ext/rubysl/openssl/ossl_x509revoked.c +43 -9
  46. data/ext/rubysl/openssl/ossl_x509store.c +309 -104
  47. data/ext/rubysl/openssl/ruby_missing.h +8 -6
  48. data/lib/openssl/buffering.rb +11 -5
  49. data/lib/openssl/cipher.rb +23 -15
  50. data/lib/openssl/digest.rb +7 -10
  51. data/lib/openssl/pkey.rb +15 -8
  52. data/lib/openssl/ssl.rb +81 -105
  53. data/lib/rubysl/openssl.rb +1 -4
  54. data/lib/rubysl/openssl/version.rb +1 -1
  55. metadata +3 -4
@@ -41,13 +41,13 @@ ossl_rand_seed(VALUE self, VALUE str)
41
41
  * The +entropy+ argument is (the lower bound of) an estimate of how much
42
42
  * randomness is contained in +str+, measured in bytes.
43
43
  *
44
- * Example:
44
+ * === Example
45
45
  *
46
46
  * pid = $$
47
47
  * now = Time.now
48
48
  * ary = [now.to_i, now.nsec, 1000, pid]
49
- * OpenSSL::Random.add(ary.join("").to_s, 0.0)
50
- * OpenSSL::Random.seed(ary.join("").to_s)
49
+ * OpenSSL::Random.add(ary.join, 0.0)
50
+ * OpenSSL::Random.seed(ary.join)
51
51
  */
52
52
  static VALUE
53
53
  ossl_rand_add(VALUE self, VALUE str, VALUE entropy)
@@ -67,9 +67,9 @@ ossl_rand_add(VALUE self, VALUE str, VALUE entropy)
67
67
  static VALUE
68
68
  ossl_rand_load_file(VALUE self, VALUE filename)
69
69
  {
70
- SafeStringValue(filename);
70
+ rb_check_safe_obj(filename);
71
71
 
72
- if(!RAND_load_file(RSTRING_PTR(filename), -1)) {
72
+ if(!RAND_load_file(StringValueCStr(filename), -1)) {
73
73
  ossl_raise(eRandomError, NULL);
74
74
  }
75
75
  return Qtrue;
@@ -86,8 +86,9 @@ ossl_rand_load_file(VALUE self, VALUE filename)
86
86
  static VALUE
87
87
  ossl_rand_write_file(VALUE self, VALUE filename)
88
88
  {
89
- SafeStringValue(filename);
90
- if (RAND_write_file(RSTRING_PTR(filename)) == -1) {
89
+ rb_check_safe_obj(filename);
90
+
91
+ if (RAND_write_file(StringValueCStr(filename)) == -1) {
91
92
  ossl_raise(eRandomError, NULL);
92
93
  }
93
94
  return Qtrue;
@@ -100,10 +101,10 @@ ossl_rand_write_file(VALUE self, VALUE filename)
100
101
  * Generates +string+ with +length+ number of cryptographically strong
101
102
  * pseudo-random bytes.
102
103
  *
103
- * Example:
104
+ * === Example
104
105
  *
105
106
  * OpenSSL::Random.random_bytes(12)
106
- * => "..."
107
+ * #=> "..."
107
108
  */
108
109
  static VALUE
109
110
  ossl_rand_bytes(VALUE self, VALUE len)
@@ -114,10 +115,8 @@ ossl_rand_bytes(VALUE self, VALUE len)
114
115
 
115
116
  str = rb_str_new(0, n);
116
117
  ret = RAND_bytes((unsigned char *)RSTRING_PTR(str), n);
117
- if (ret == 0){
118
- char buf[256];
119
- ERR_error_string_n(ERR_get_error(), buf, 256);
120
- ossl_raise(eRandomError, "RAND_bytes error: %s", buf);
118
+ if (ret == 0) {
119
+ ossl_raise(eRandomError, "RAND_bytes");
121
120
  } else if (ret == -1) {
122
121
  ossl_raise(eRandomError, "RAND_bytes is not supported");
123
122
  }
@@ -125,6 +124,7 @@ ossl_rand_bytes(VALUE self, VALUE len)
125
124
  return str;
126
125
  }
127
126
 
127
+ #if defined(HAVE_RAND_PSEUDO_BYTES)
128
128
  /*
129
129
  * call-seq:
130
130
  * pseudo_bytes(length) -> string
@@ -134,10 +134,10 @@ ossl_rand_bytes(VALUE self, VALUE len)
134
134
  * Pseudo-random byte sequences generated by ::pseudo_bytes will be unique if
135
135
  * they are of sufficient length, but are not necessarily unpredictable.
136
136
  *
137
- * Example:
137
+ * === Example
138
138
  *
139
139
  * OpenSSL::Random.pseudo_bytes(12)
140
- * => "..."
140
+ * #=> "..."
141
141
  */
142
142
  static VALUE
143
143
  ossl_rand_pseudo_bytes(VALUE self, VALUE len)
@@ -146,12 +146,13 @@ ossl_rand_pseudo_bytes(VALUE self, VALUE len)
146
146
  int n = NUM2INT(len);
147
147
 
148
148
  str = rb_str_new(0, n);
149
- if (!RAND_pseudo_bytes((unsigned char *)RSTRING_PTR(str), n)) {
149
+ if (RAND_pseudo_bytes((unsigned char *)RSTRING_PTR(str), n) < 1) {
150
150
  ossl_raise(eRandomError, NULL);
151
151
  }
152
152
 
153
153
  return str;
154
154
  }
155
+ #endif
155
156
 
156
157
  #ifdef HAVE_RAND_EGD
157
158
  /*
@@ -163,9 +164,9 @@ ossl_rand_pseudo_bytes(VALUE self, VALUE len)
163
164
  static VALUE
164
165
  ossl_rand_egd(VALUE self, VALUE filename)
165
166
  {
166
- SafeStringValue(filename);
167
+ rb_check_safe_obj(filename);
167
168
 
168
- if(!RAND_egd(RSTRING_PTR(filename))) {
169
+ if (RAND_egd(StringValueCStr(filename)) == -1) {
169
170
  ossl_raise(eRandomError, NULL);
170
171
  }
171
172
  return Qtrue;
@@ -185,9 +186,9 @@ ossl_rand_egd_bytes(VALUE self, VALUE filename, VALUE len)
185
186
  {
186
187
  int n = NUM2INT(len);
187
188
 
188
- SafeStringValue(filename);
189
+ rb_check_safe_obj(filename);
189
190
 
190
- if (!RAND_egd_bytes(RSTRING_PTR(filename), n)) {
191
+ if (RAND_egd_bytes(StringValueCStr(filename), n) == -1) {
191
192
  ossl_raise(eRandomError, NULL);
192
193
  }
193
194
  return Qtrue;
@@ -213,7 +214,8 @@ void
213
214
  Init_ossl_rand(void)
214
215
  {
215
216
  #if 0
216
- mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
217
+ mOSSL = rb_define_module("OpenSSL");
218
+ eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
217
219
  #endif
218
220
 
219
221
  mRandom = rb_define_module_under(mOSSL, "Random");
@@ -225,7 +227,9 @@ Init_ossl_rand(void)
225
227
  rb_define_module_function(mRandom, "load_random_file", ossl_rand_load_file, 1);
226
228
  rb_define_module_function(mRandom, "write_random_file", ossl_rand_write_file, 1);
227
229
  rb_define_module_function(mRandom, "random_bytes", ossl_rand_bytes, 1);
230
+ #if defined(HAVE_RAND_PSEUDO_BYTES)
228
231
  rb_define_module_function(mRandom, "pseudo_bytes", ossl_rand_pseudo_bytes, 1);
232
+ #endif
229
233
  #ifdef HAVE_RAND_EGD
230
234
  rb_define_module_function(mRandom, "egd", ossl_rand_egd, 1);
231
235
  rb_define_module_function(mRandom, "egd_bytes", ossl_rand_egd_bytes, 2);
@@ -11,10 +11,6 @@
11
11
  */
12
12
  #include "ossl.h"
13
13
 
14
- #if defined(HAVE_UNISTD_H)
15
- # include <unistd.h> /* for read(), and write() */
16
- #endif
17
-
18
14
  #define numberof(ary) (int)(sizeof(ary)/sizeof((ary)[0]))
19
15
 
20
16
  #ifdef _WIN32
@@ -36,87 +32,55 @@ VALUE cSSLSocket;
36
32
  static VALUE eSSLErrorWaitReadable;
37
33
  static VALUE eSSLErrorWaitWritable;
38
34
 
39
- #define ossl_sslctx_set_cert(o,v) rb_iv_set((o),"@cert",(v))
40
- #define ossl_sslctx_set_key(o,v) rb_iv_set((o),"@key",(v))
41
- #define ossl_sslctx_set_client_ca(o,v) rb_iv_set((o),"@client_ca",(v))
42
- #define ossl_sslctx_set_ca_file(o,v) rb_iv_set((o),"@ca_file",(v))
43
- #define ossl_sslctx_set_ca_path(o,v) rb_iv_set((o),"@ca_path",(v))
44
- #define ossl_sslctx_set_timeout(o,v) rb_iv_set((o),"@timeout",(v))
45
- #define ossl_sslctx_set_verify_mode(o,v) rb_iv_set((o),"@verify_mode",(v))
46
- #define ossl_sslctx_set_verify_dep(o,v) rb_iv_set((o),"@verify_depth",(v))
47
- #define ossl_sslctx_set_verify_cb(o,v) rb_iv_set((o),"@verify_callback",(v))
48
- #define ossl_sslctx_set_cert_store(o,v) rb_iv_set((o),"@cert_store",(v))
49
- #define ossl_sslctx_set_extra_cert(o,v) rb_iv_set((o),"@extra_chain_cert",(v))
50
- #define ossl_sslctx_set_client_cert_cb(o,v) rb_iv_set((o),"@client_cert_cb",(v))
51
- #define ossl_sslctx_set_sess_id_ctx(o, v) rb_iv_set((o),"@session_id_context",(v))
52
-
53
- #define ossl_sslctx_get_cert(o) rb_iv_get((o),"@cert")
54
- #define ossl_sslctx_get_key(o) rb_iv_get((o),"@key")
55
- #define ossl_sslctx_get_client_ca(o) rb_iv_get((o),"@client_ca")
56
- #define ossl_sslctx_get_ca_file(o) rb_iv_get((o),"@ca_file")
57
- #define ossl_sslctx_get_ca_path(o) rb_iv_get((o),"@ca_path")
58
- #define ossl_sslctx_get_timeout(o) rb_iv_get((o),"@timeout")
59
- #define ossl_sslctx_get_verify_mode(o) rb_iv_get((o),"@verify_mode")
60
- #define ossl_sslctx_get_verify_dep(o) rb_iv_get((o),"@verify_depth")
61
- #define ossl_sslctx_get_verify_cb(o) rb_iv_get((o),"@verify_callback")
62
- #define ossl_sslctx_get_cert_store(o) rb_iv_get((o),"@cert_store")
63
- #define ossl_sslctx_get_extra_cert(o) rb_iv_get((o),"@extra_chain_cert")
64
- #define ossl_sslctx_get_client_cert_cb(o) rb_iv_get((o),"@client_cert_cb")
65
- #define ossl_sslctx_get_tmp_ecdh_cb(o) rb_iv_get((o),"@tmp_ecdh_callback")
66
- #define ossl_sslctx_get_sess_id_ctx(o) rb_iv_get((o),"@session_id_context")
67
-
68
- #define ossl_ssl_get_io(o) rb_iv_get((o),"@io")
69
- #define ossl_ssl_get_ctx(o) rb_iv_get((o),"@context")
70
- #define ossl_ssl_get_x509(o) rb_iv_get((o),"@x509")
71
- #define ossl_ssl_get_key(o) rb_iv_get((o),"@key")
72
-
73
- #define ossl_ssl_set_x509(o,v) rb_iv_set((o),"@x509",(v))
74
- #define ossl_ssl_set_key(o,v) rb_iv_set((o),"@key",(v))
75
- #define ossl_ssl_set_tmp_dh(o,v) rb_iv_set((o),"@tmp_dh",(v))
76
- #define ossl_ssl_set_tmp_ecdh(o,v) rb_iv_set((o),"@tmp_ecdh",(v))
77
-
78
- static ID ID_callback_state;
79
-
35
+ static ID ID_callback_state, id_tmp_dh_callback, id_tmp_ecdh_callback,
36
+ id_npn_protocols_encoded;
80
37
  static VALUE sym_exception, sym_wait_readable, sym_wait_writable;
81
38
 
39
+ static ID id_i_cert_store, id_i_ca_file, id_i_ca_path, id_i_verify_mode,
40
+ id_i_verify_depth, id_i_verify_callback, id_i_client_ca,
41
+ 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,
43
+ id_i_session_id_context, id_i_session_get_cb, id_i_session_new_cb,
44
+ id_i_session_remove_cb, id_i_npn_select_cb, id_i_npn_protocols,
45
+ id_i_alpn_select_cb, id_i_alpn_protocols, id_i_servername_cb,
46
+ id_i_verify_hostname;
47
+ static ID id_i_io, id_i_context, id_i_hostname;
48
+
82
49
  /*
83
50
  * SSLContext class
84
51
  */
85
52
  static const struct {
86
53
  const char *name;
87
- SSL_METHOD *(*func)(void);
54
+ SSL_METHOD *(*func)(void); /* FIXME: constify when dropping 0.9.8 */
55
+ int version;
88
56
  } ossl_ssl_method_tab[] = {
89
- #define OSSL_SSL_METHOD_ENTRY(name) { #name, (SSL_METHOD *(*)(void))name##_method }
90
- OSSL_SSL_METHOD_ENTRY(TLSv1),
91
- OSSL_SSL_METHOD_ENTRY(TLSv1_server),
92
- OSSL_SSL_METHOD_ENTRY(TLSv1_client),
93
- #if defined(HAVE_TLSV1_2_METHOD) && defined(HAVE_TLSV1_2_SERVER_METHOD) && \
94
- defined(HAVE_TLSV1_2_CLIENT_METHOD)
95
- OSSL_SSL_METHOD_ENTRY(TLSv1_2),
96
- OSSL_SSL_METHOD_ENTRY(TLSv1_2_server),
97
- OSSL_SSL_METHOD_ENTRY(TLSv1_2_client),
57
+ #if defined(HAVE_SSL_CTX_SET_MIN_PROTO_VERSION)
58
+ #define OSSL_SSL_METHOD_ENTRY(name, version) \
59
+ { #name, (SSL_METHOD *(*)(void))TLS_method, version }, \
60
+ { #name"_server", (SSL_METHOD *(*)(void))TLS_server_method, version }, \
61
+ { #name"_client", (SSL_METHOD *(*)(void))TLS_client_method, version }
62
+ #else
63
+ #define OSSL_SSL_METHOD_ENTRY(name, version) \
64
+ { #name, (SSL_METHOD *(*)(void))name##_method, version }, \
65
+ { #name"_server", (SSL_METHOD *(*)(void))name##_server_method, version }, \
66
+ { #name"_client", (SSL_METHOD *(*)(void))name##_client_method, version }
98
67
  #endif
99
- #if defined(HAVE_TLSV1_1_METHOD) && defined(HAVE_TLSV1_1_SERVER_METHOD) && \
100
- defined(HAVE_TLSV1_1_CLIENT_METHOD)
101
- OSSL_SSL_METHOD_ENTRY(TLSv1_1),
102
- OSSL_SSL_METHOD_ENTRY(TLSv1_1_server),
103
- OSSL_SSL_METHOD_ENTRY(TLSv1_1_client),
68
+ #if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL2_METHOD) && defined(HAVE_SSLV2_METHOD)
69
+ OSSL_SSL_METHOD_ENTRY(SSLv2, SSL2_VERSION),
104
70
  #endif
105
- #if defined(HAVE_SSLV2_METHOD) && defined(HAVE_SSLV2_SERVER_METHOD) && \
106
- defined(HAVE_SSLV2_CLIENT_METHOD)
107
- OSSL_SSL_METHOD_ENTRY(SSLv2),
108
- OSSL_SSL_METHOD_ENTRY(SSLv2_server),
109
- OSSL_SSL_METHOD_ENTRY(SSLv2_client),
71
+ #if !defined(OPENSSL_NO_SSL3) && !defined(OPENSSL_NO_SSL3_METHOD) && defined(HAVE_SSLV3_METHOD)
72
+ OSSL_SSL_METHOD_ENTRY(SSLv3, SSL3_VERSION),
110
73
  #endif
111
- #if defined(HAVE_SSLV3_METHOD) && defined(HAVE_SSLV3_SERVER_METHOD) && \
112
- defined(HAVE_SSLV3_CLIENT_METHOD)
113
- OSSL_SSL_METHOD_ENTRY(SSLv3),
114
- OSSL_SSL_METHOD_ENTRY(SSLv3_server),
115
- OSSL_SSL_METHOD_ENTRY(SSLv3_client),
74
+ #if !defined(OPENSSL_NO_TLS1) && !defined(OPENSSL_NO_TLS1_METHOD)
75
+ OSSL_SSL_METHOD_ENTRY(TLSv1, TLS1_VERSION),
116
76
  #endif
117
- OSSL_SSL_METHOD_ENTRY(SSLv23),
118
- OSSL_SSL_METHOD_ENTRY(SSLv23_server),
119
- OSSL_SSL_METHOD_ENTRY(SSLv23_client),
77
+ #if !defined(OPENSSL_NO_TLS1_1) && !defined(OPENSSL_NO_TLS1_1_METHOD) && defined(HAVE_TLSV1_1_METHOD)
78
+ OSSL_SSL_METHOD_ENTRY(TLSv1_1, TLS1_1_VERSION),
79
+ #endif
80
+ #if !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_TLS1_2_METHOD) && defined(HAVE_TLSV1_2_METHOD)
81
+ OSSL_SSL_METHOD_ENTRY(TLSv1_2, TLS1_2_VERSION),
82
+ #endif
83
+ OSSL_SSL_METHOD_ENTRY(SSLv23, 0),
120
84
  #undef OSSL_SSL_METHOD_ENTRY
121
85
  };
122
86
 
@@ -128,8 +92,10 @@ static void
128
92
  ossl_sslctx_free(void *ptr)
129
93
  {
130
94
  SSL_CTX *ctx = ptr;
95
+ #if !defined(HAVE_X509_STORE_UP_REF)
131
96
  if(ctx && SSL_CTX_get_ex_data(ctx, ossl_ssl_ex_store_p)== (void*)1)
132
97
  ctx->cert_store = NULL;
98
+ #endif
133
99
  SSL_CTX_free(ctx);
134
100
  }
135
101
 
@@ -145,7 +111,8 @@ static VALUE
145
111
  ossl_sslctx_s_alloc(VALUE klass)
146
112
  {
147
113
  SSL_CTX *ctx;
148
- long mode = SSL_MODE_ENABLE_PARTIAL_WRITE;
114
+ long mode = SSL_MODE_ENABLE_PARTIAL_WRITE |
115
+ SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER;
149
116
  VALUE obj;
150
117
 
151
118
  #ifdef SSL_MODE_RELEASE_BUFFERS
@@ -161,6 +128,18 @@ ossl_sslctx_s_alloc(VALUE klass)
161
128
  RTYPEDDATA_DATA(obj) = ctx;
162
129
  SSL_CTX_set_ex_data(ctx, ossl_ssl_ex_ptr_idx, (void*)obj);
163
130
 
131
+ #if !defined(OPENSSL_NO_EC) && defined(HAVE_SSL_CTX_SET_ECDH_AUTO)
132
+ /* We use SSL_CTX_set1_curves_list() to specify the curve used in ECDH. It
133
+ * allows to specify multiple curve names and OpenSSL will select
134
+ * automatically from them. In OpenSSL 1.0.2, the automatic selection has to
135
+ * be enabled explicitly. But OpenSSL 1.1.0 removed the knob and it is
136
+ * always enabled. To uniform the behavior, we enable the automatic
137
+ * selection also in 1.0.2. Users can still disable ECDH by removing ECDH
138
+ * cipher suites by SSLContext#ciphers=. */
139
+ if (!SSL_CTX_set_ecdh_auto(ctx, 1))
140
+ ossl_raise(eSSLError, "SSL_CTX_set_ecdh_auto");
141
+ #endif
142
+
164
143
  return obj;
165
144
  }
166
145
 
@@ -169,146 +148,212 @@ ossl_sslctx_s_alloc(VALUE klass)
169
148
  * ctx.ssl_version = :TLSv1
170
149
  * ctx.ssl_version = "SSLv23_client"
171
150
  *
151
+ * Sets the SSL/TLS protocol version for the context. This forces connections to
152
+ * use only the specified protocol version.
153
+ *
172
154
  * You can get a list of valid versions with OpenSSL::SSL::SSLContext::METHODS
173
155
  */
174
156
  static VALUE
175
157
  ossl_sslctx_set_ssl_version(VALUE self, VALUE ssl_method)
176
158
  {
177
- SSL_METHOD *method = NULL;
159
+ SSL_CTX *ctx;
178
160
  const char *s;
179
161
  VALUE m = ssl_method;
180
162
  int i;
181
163
 
182
- SSL_CTX *ctx;
164
+ GetSSLCTX(self, ctx);
183
165
  if (RB_TYPE_P(ssl_method, T_SYMBOL))
184
166
  m = rb_sym2str(ssl_method);
185
167
  s = StringValueCStr(m);
186
168
  for (i = 0; i < numberof(ossl_ssl_method_tab); i++) {
187
169
  if (strcmp(ossl_ssl_method_tab[i].name, s) == 0) {
188
- method = ossl_ssl_method_tab[i].func();
189
- break;
170
+ #if defined(HAVE_SSL_CTX_SET_MIN_PROTO_VERSION)
171
+ int version = ossl_ssl_method_tab[i].version;
172
+ #endif
173
+ SSL_METHOD *method = ossl_ssl_method_tab[i].func();
174
+
175
+ if (SSL_CTX_set_ssl_version(ctx, method) != 1)
176
+ ossl_raise(eSSLError, "SSL_CTX_set_ssl_version");
177
+
178
+ #if defined(HAVE_SSL_CTX_SET_MIN_PROTO_VERSION)
179
+ if (!SSL_CTX_set_min_proto_version(ctx, version))
180
+ ossl_raise(eSSLError, "SSL_CTX_set_min_proto_version");
181
+ if (!SSL_CTX_set_max_proto_version(ctx, version))
182
+ ossl_raise(eSSLError, "SSL_CTX_set_max_proto_version");
183
+ #endif
184
+ return ssl_method;
190
185
  }
191
186
  }
192
- if (!method) {
193
- ossl_raise(rb_eArgError, "unknown SSL method `%"PRIsVALUE"'.", m);
194
- }
195
- GetSSLCTX(self, ctx);
196
- if (SSL_CTX_set_ssl_version(ctx, method) != 1) {
197
- ossl_raise(eSSLError, "SSL_CTX_set_ssl_version");
198
- }
199
187
 
200
- return ssl_method;
188
+ ossl_raise(rb_eArgError, "unknown SSL method `%"PRIsVALUE"'.", m);
201
189
  }
202
190
 
203
191
  static VALUE
204
192
  ossl_call_client_cert_cb(VALUE obj)
205
193
  {
206
- VALUE cb, ary, cert, key;
194
+ VALUE ctx_obj, cb, ary, cert, key;
195
+
196
+ ctx_obj = rb_attr_get(obj, id_i_context);
197
+ cb = rb_attr_get(ctx_obj, id_i_client_cert_cb);
198
+ if (NIL_P(cb))
199
+ return Qnil;
207
200
 
208
- cb = rb_funcall(obj, rb_intern("client_cert_cb"), 0);
209
- if (NIL_P(cb)) return Qfalse;
210
201
  ary = rb_funcall(cb, rb_intern("call"), 1, obj);
211
202
  Check_Type(ary, T_ARRAY);
212
203
  GetX509CertPtr(cert = rb_ary_entry(ary, 0));
213
- GetPKeyPtr(key = rb_ary_entry(ary, 1));
214
- ossl_ssl_set_x509(obj, cert);
215
- ossl_ssl_set_key(obj, key);
204
+ GetPrivPKeyPtr(key = rb_ary_entry(ary, 1));
216
205
 
217
- return Qtrue;
206
+ return rb_ary_new3(2, cert, key);
218
207
  }
219
208
 
220
209
  static int
221
210
  ossl_client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
222
211
  {
223
- VALUE obj, success;
212
+ VALUE obj, ret;
224
213
 
225
214
  obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
226
- success = rb_protect(ossl_call_client_cert_cb, obj, NULL);
227
- if (!RTEST(success)) return 0;
228
- *x509 = DupX509CertPtr(ossl_ssl_get_x509(obj));
229
- *pkey = DupPKeyPtr(ossl_ssl_get_key(obj));
215
+ ret = rb_protect(ossl_call_client_cert_cb, obj, NULL);
216
+ if (NIL_P(ret))
217
+ return 0;
218
+
219
+ *x509 = DupX509CertPtr(RARRAY_AREF(ret, 0));
220
+ *pkey = DupPKeyPtr(RARRAY_AREF(ret, 1));
230
221
 
231
222
  return 1;
232
223
  }
233
224
 
234
- #if !defined(OPENSSL_NO_DH)
235
- static VALUE
236
- ossl_call_tmp_dh_callback(VALUE args)
225
+ #if !defined(OPENSSL_NO_DH) || \
226
+ !defined(OPENSSL_NO_EC) && defined(HAVE_SSL_CTX_SET_TMP_ECDH_CALLBACK)
227
+ struct tmp_dh_callback_args {
228
+ VALUE ssl_obj;
229
+ ID id;
230
+ int type;
231
+ int is_export;
232
+ int keylength;
233
+ };
234
+
235
+ static EVP_PKEY *
236
+ ossl_call_tmp_dh_callback(struct tmp_dh_callback_args *args)
237
237
  {
238
238
  VALUE cb, dh;
239
239
  EVP_PKEY *pkey;
240
240
 
241
- cb = rb_funcall(rb_ary_entry(args, 0), rb_intern("tmp_dh_callback"), 0);
242
-
243
- if (NIL_P(cb)) return Qfalse;
244
- dh = rb_apply(cb, rb_intern("call"), args);
241
+ cb = rb_funcall(args->ssl_obj, args->id, 0);
242
+ if (NIL_P(cb))
243
+ return NULL;
244
+ dh = rb_funcall(cb, rb_intern("call"), 3,
245
+ args->ssl_obj, INT2NUM(args->is_export), INT2NUM(args->keylength));
245
246
  pkey = GetPKeyPtr(dh);
246
- if (EVP_PKEY_type(pkey->type) != EVP_PKEY_DH) return Qfalse;
247
+ if (EVP_PKEY_base_id(pkey) != args->type)
248
+ return NULL;
247
249
 
248
- return dh;
250
+ return pkey;
249
251
  }
252
+ #endif
250
253
 
251
- static DH*
254
+ #if !defined(OPENSSL_NO_DH)
255
+ static DH *
252
256
  ossl_tmp_dh_callback(SSL *ssl, int is_export, int keylength)
253
257
  {
254
- VALUE args, dh, rb_ssl;
258
+ VALUE rb_ssl;
259
+ EVP_PKEY *pkey;
260
+ struct tmp_dh_callback_args args;
261
+ int state;
255
262
 
256
263
  rb_ssl = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
264
+ args.ssl_obj = rb_ssl;
265
+ args.id = id_tmp_dh_callback;
266
+ args.is_export = is_export;
267
+ args.keylength = keylength;
268
+ args.type = EVP_PKEY_DH;
269
+
270
+ pkey = (EVP_PKEY *)rb_protect((VALUE (*)(VALUE))ossl_call_tmp_dh_callback,
271
+ (VALUE)&args, &state);
272
+ if (state) {
273
+ rb_ivar_set(rb_ssl, ID_callback_state, INT2NUM(state));
274
+ return NULL;
275
+ }
276
+ if (!pkey)
277
+ return NULL;
257
278
 
258
- args = rb_ary_new_from_args(3, rb_ssl, INT2FIX(is_export), INT2FIX(keylength));
259
-
260
- dh = rb_protect(ossl_call_tmp_dh_callback, args, NULL);
261
- if (!RTEST(dh)) return NULL;
262
- ossl_ssl_set_tmp_dh(rb_ssl, dh);
263
-
264
- return GetPKeyPtr(dh)->pkey.dh;
279
+ return EVP_PKEY_get0_DH(pkey);
265
280
  }
266
281
  #endif /* OPENSSL_NO_DH */
267
282
 
268
- #if !defined(OPENSSL_NO_EC)
269
- static VALUE
270
- ossl_call_tmp_ecdh_callback(VALUE args)
283
+ #if !defined(OPENSSL_NO_EC) && defined(HAVE_SSL_CTX_SET_TMP_ECDH_CALLBACK)
284
+ static EC_KEY *
285
+ ossl_tmp_ecdh_callback(SSL *ssl, int is_export, int keylength)
271
286
  {
272
- VALUE cb, ecdh;
287
+ VALUE rb_ssl;
273
288
  EVP_PKEY *pkey;
289
+ struct tmp_dh_callback_args args;
290
+ int state;
274
291
 
275
- cb = rb_funcall(rb_ary_entry(args, 0), rb_intern("tmp_ecdh_callback"), 0);
276
-
277
- if (NIL_P(cb)) return Qfalse;
278
- ecdh = rb_apply(cb, rb_intern("call"), args);
279
- pkey = GetPKeyPtr(ecdh);
280
- if (EVP_PKEY_type(pkey->type) != EVP_PKEY_EC) return Qfalse;
292
+ rb_ssl = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
293
+ args.ssl_obj = rb_ssl;
294
+ args.id = id_tmp_ecdh_callback;
295
+ args.is_export = is_export;
296
+ args.keylength = keylength;
297
+ args.type = EVP_PKEY_EC;
298
+
299
+ pkey = (EVP_PKEY *)rb_protect((VALUE (*)(VALUE))ossl_call_tmp_dh_callback,
300
+ (VALUE)&args, &state);
301
+ if (state) {
302
+ rb_ivar_set(rb_ssl, ID_callback_state, INT2NUM(state));
303
+ return NULL;
304
+ }
305
+ if (!pkey)
306
+ return NULL;
281
307
 
282
- return ecdh;
308
+ return EVP_PKEY_get0_EC_KEY(pkey);
283
309
  }
310
+ #endif
284
311
 
285
- static EC_KEY*
286
- ossl_tmp_ecdh_callback(SSL *ssl, int is_export, int keylength)
312
+ static VALUE
313
+ call_verify_certificate_identity(VALUE ctx_v)
287
314
  {
288
- VALUE args, ecdh, rb_ssl;
289
-
290
- rb_ssl = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
315
+ X509_STORE_CTX *ctx = (X509_STORE_CTX *)ctx_v;
316
+ SSL *ssl;
317
+ VALUE ssl_obj, hostname, cert_obj;
291
318
 
292
- args = rb_ary_new_from_args(3, rb_ssl, INT2FIX(is_export), INT2FIX(keylength));
319
+ ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
320
+ ssl_obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
321
+ hostname = rb_attr_get(ssl_obj, id_i_hostname);
293
322
 
294
- ecdh = rb_protect(ossl_call_tmp_ecdh_callback, args, NULL);
295
- if (!RTEST(ecdh)) return NULL;
296
- ossl_ssl_set_tmp_ecdh(rb_ssl, ecdh);
323
+ if (!RTEST(hostname)) {
324
+ rb_warning("verify_hostname requires hostname to be set");
325
+ return Qtrue;
326
+ }
297
327
 
298
- return GetPKeyPtr(ecdh)->pkey.ec;
328
+ cert_obj = ossl_x509_new(X509_STORE_CTX_get_current_cert(ctx));
329
+ return rb_funcall(mSSL, rb_intern("verify_certificate_identity"), 2,
330
+ cert_obj, hostname);
299
331
  }
300
- #endif
301
332
 
302
333
  static int
303
334
  ossl_ssl_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
304
335
  {
305
- VALUE cb;
336
+ VALUE cb, ssl_obj, sslctx_obj, verify_hostname, ret;
306
337
  SSL *ssl;
338
+ int status;
307
339
 
308
340
  ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
309
341
  cb = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_vcb_idx);
310
- X509_STORE_CTX_set_ex_data(ctx, ossl_verify_cb_idx, (void*)cb);
311
- return ossl_verify_cb(preverify_ok, ctx);
342
+ ssl_obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
343
+ sslctx_obj = rb_attr_get(ssl_obj, id_i_context);
344
+ verify_hostname = rb_attr_get(sslctx_obj, id_i_verify_hostname);
345
+
346
+ if (preverify_ok && RTEST(verify_hostname) && !SSL_is_server(ssl) &&
347
+ !X509_STORE_CTX_get_error_depth(ctx)) {
348
+ ret = rb_protect(call_verify_certificate_identity, (VALUE)ctx, &status);
349
+ if (status) {
350
+ rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(status));
351
+ return 0;
352
+ }
353
+ preverify_ok = ret == Qtrue;
354
+ }
355
+
356
+ return ossl_verify_cb_call(cb, preverify_ok, ctx);
312
357
  }
313
358
 
314
359
  static VALUE
@@ -327,7 +372,11 @@ ossl_call_session_get_cb(VALUE ary)
327
372
 
328
373
  /* this method is currently only called for servers (in OpenSSL <= 0.9.8e) */
329
374
  static SSL_SESSION *
375
+ #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
376
+ ossl_sslctx_session_get_cb(SSL *ssl, const unsigned char *buf, int len, int *copy)
377
+ #else
330
378
  ossl_sslctx_session_get_cb(SSL *ssl, unsigned char *buf, int len, int *copy)
379
+ #endif
331
380
  {
332
381
  VALUE ary, ssl_obj, ret_obj;
333
382
  SSL_SESSION *sess;
@@ -384,7 +433,7 @@ ossl_sslctx_session_new_cb(SSL *ssl, SSL_SESSION *sess)
384
433
  return 1;
385
434
  ssl_obj = (VALUE)ptr;
386
435
  sess_obj = rb_obj_alloc(cSSLSession);
387
- CRYPTO_add(&sess->references, 1, CRYPTO_LOCK_SSL_SESSION);
436
+ SSL_SESSION_up_ref(sess);
388
437
  DATA_PTR(sess_obj) = sess;
389
438
 
390
439
  ary = rb_ary_new2(2);
@@ -414,7 +463,7 @@ ossl_call_session_remove_cb(VALUE ary)
414
463
  Check_Type(ary, T_ARRAY);
415
464
  sslctx_obj = rb_ary_entry(ary, 0);
416
465
 
417
- cb = rb_iv_get(sslctx_obj, "@session_remove_cb");
466
+ cb = rb_attr_get(sslctx_obj, id_i_session_remove_cb);
418
467
  if (NIL_P(cb)) return Qnil;
419
468
 
420
469
  return rb_funcall(cb, rb_intern("call"), 1, ary);
@@ -427,20 +476,27 @@ ossl_sslctx_session_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
427
476
  void *ptr;
428
477
  int state = 0;
429
478
 
479
+ /*
480
+ * This callback is also called for all sessions in the internal store
481
+ * when SSL_CTX_free() is called.
482
+ */
483
+ if (rb_during_gc())
484
+ return;
485
+
430
486
  OSSL_Debug("SSL SESSION remove callback entered");
431
487
 
432
488
  if ((ptr = SSL_CTX_get_ex_data(ctx, ossl_ssl_ex_ptr_idx)) == NULL)
433
489
  return;
434
490
  sslctx_obj = (VALUE)ptr;
435
491
  sess_obj = rb_obj_alloc(cSSLSession);
436
- CRYPTO_add(&sess->references, 1, CRYPTO_LOCK_SSL_SESSION);
492
+ SSL_SESSION_up_ref(sess);
437
493
  DATA_PTR(sess_obj) = sess;
438
494
 
439
495
  ary = rb_ary_new2(2);
440
496
  rb_ary_push(ary, sslctx_obj);
441
497
  rb_ary_push(ary, sess_obj);
442
498
 
443
- rb_protect((VALUE(*)_((VALUE)))ossl_call_session_remove_cb, ary, &state);
499
+ rb_protect(ossl_call_session_remove_cb, ary, &state);
444
500
  if (state) {
445
501
  /*
446
502
  the SSL_CTX is frozen, nowhere to save state.
@@ -476,9 +532,8 @@ ossl_call_servername_cb(VALUE ary)
476
532
  Check_Type(ary, T_ARRAY);
477
533
  ssl_obj = rb_ary_entry(ary, 0);
478
534
 
479
- sslctx_obj = rb_iv_get(ssl_obj, "@context");
480
- if (NIL_P(sslctx_obj)) return Qnil;
481
- cb = rb_iv_get(sslctx_obj, "@servername_cb");
535
+ sslctx_obj = rb_attr_get(ssl_obj, id_i_context);
536
+ cb = rb_attr_get(sslctx_obj, id_i_servername_cb);
482
537
  if (NIL_P(cb)) return Qnil;
483
538
 
484
539
  ret_obj = rb_funcall(cb, rb_intern("call"), 1, ary);
@@ -490,9 +545,10 @@ ossl_call_servername_cb(VALUE ary)
490
545
  GetSSL(ssl_obj, ssl);
491
546
  GetSSLCTX(ret_obj, ctx2);
492
547
  SSL_set_SSL_CTX(ssl, ctx2);
493
- rb_iv_set(ssl_obj, "@context", ret_obj);
548
+ rb_ivar_set(ssl_obj, id_i_context, ret_obj);
494
549
  } else if (!NIL_P(ret_obj)) {
495
- ossl_raise(rb_eArgError, "servername_cb must return an OpenSSL::SSL::SSLContext object or nil");
550
+ ossl_raise(rb_eArgError, "servername_cb must return an "
551
+ "OpenSSL::SSL::SSLContext object or nil");
496
552
  }
497
553
 
498
554
  return ret_obj;
@@ -516,7 +572,7 @@ ssl_servername_cb(SSL *ssl, int *ad, void *arg)
516
572
  rb_ary_push(ary, ssl_obj);
517
573
  rb_ary_push(ary, rb_str_new2(servername));
518
574
 
519
- rb_protect((VALUE(*)_((VALUE)))ossl_call_servername_cb, ary, &state);
575
+ rb_protect(ossl_call_servername_cb, ary, &state);
520
576
  if (state) {
521
577
  rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(state));
522
578
  return SSL_TLSEXT_ERR_ALERT_FATAL;
@@ -536,15 +592,15 @@ ssl_renegotiation_cb(const SSL *ssl)
536
592
  ossl_raise(eSSLError, "SSL object could not be retrieved");
537
593
  ssl_obj = (VALUE)ptr;
538
594
 
539
- sslctx_obj = rb_iv_get(ssl_obj, "@context");
540
- if (NIL_P(sslctx_obj)) return;
541
- cb = rb_iv_get(sslctx_obj, "@renegotiation_cb");
595
+ sslctx_obj = rb_attr_get(ssl_obj, id_i_context);
596
+ cb = rb_attr_get(sslctx_obj, id_i_renegotiation_cb);
542
597
  if (NIL_P(cb)) return;
543
598
 
544
599
  (void) rb_funcall(cb, rb_intern("call"), 1, ssl_obj);
545
600
  }
546
601
 
547
- #if defined(HAVE_SSL_CTX_SET_NEXT_PROTO_SELECT_CB) || defined(HAVE_SSL_CTX_SET_ALPN_SELECT_CB)
602
+ #if defined(HAVE_SSL_CTX_SET_NEXT_PROTO_SELECT_CB) || \
603
+ defined(HAVE_SSL_CTX_SET_ALPN_SELECT_CB)
548
604
  static VALUE
549
605
  ssl_npn_encode_protocol_i(VALUE cur, VALUE encoded)
550
606
  {
@@ -562,20 +618,25 @@ ssl_npn_encode_protocol_i(VALUE cur, VALUE encoded)
562
618
  static VALUE
563
619
  ssl_encode_npn_protocols(VALUE protocols)
564
620
  {
565
- VALUE encoded = rb_str_new2("");
621
+ VALUE encoded = rb_str_new(NULL, 0);
566
622
  rb_iterate(rb_each, protocols, ssl_npn_encode_protocol_i, encoded);
567
- StringValueCStr(encoded);
568
623
  return encoded;
569
624
  }
570
625
 
571
- static int
572
- ssl_npn_select_cb_common(VALUE cb, const unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen)
626
+ struct npn_select_cb_common_args {
627
+ VALUE cb;
628
+ const unsigned char *in;
629
+ unsigned inlen;
630
+ };
631
+
632
+ static VALUE
633
+ npn_select_cb_common_i(VALUE tmp)
573
634
  {
574
- VALUE selected;
575
- long len;
576
- VALUE protocols = rb_ary_new();
635
+ struct npn_select_cb_common_args *args = (void *)tmp;
636
+ const unsigned char *in = args->in, *in_end = in + args->inlen;
577
637
  unsigned char l;
578
- const unsigned char *in_end = in + inlen;
638
+ long len;
639
+ VALUE selected, protocols = rb_ary_new();
579
640
 
580
641
  /* assume OpenSSL verifies this format */
581
642
  /* The format is len_1|proto_1|...|len_n|proto_n */
@@ -585,24 +646,50 @@ ssl_npn_select_cb_common(VALUE cb, const unsigned char **out, unsigned char *out
585
646
  in += l;
586
647
  }
587
648
 
588
- selected = rb_funcall(cb, rb_intern("call"), 1, protocols);
649
+ selected = rb_funcall(args->cb, rb_intern("call"), 1, protocols);
589
650
  StringValue(selected);
590
651
  len = RSTRING_LEN(selected);
591
652
  if (len < 1 || len >= 256) {
592
653
  ossl_raise(eSSLError, "Selected protocol name must have length 1..255");
593
654
  }
655
+
656
+ return selected;
657
+ }
658
+
659
+ static int
660
+ ssl_npn_select_cb_common(SSL *ssl, VALUE cb, const unsigned char **out,
661
+ unsigned char *outlen, const unsigned char *in,
662
+ unsigned int inlen)
663
+ {
664
+ VALUE selected;
665
+ int status;
666
+ struct npn_select_cb_common_args args;
667
+
668
+ args.cb = cb;
669
+ args.in = in;
670
+ args.inlen = inlen;
671
+
672
+ selected = rb_protect(npn_select_cb_common_i, (VALUE)&args, &status);
673
+ if (status) {
674
+ VALUE ssl_obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
675
+
676
+ rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(status));
677
+ return SSL_TLSEXT_ERR_ALERT_FATAL;
678
+ }
679
+
594
680
  *out = (unsigned char *)RSTRING_PTR(selected);
595
- *outlen = (unsigned char)len;
681
+ *outlen = (unsigned char)RSTRING_LEN(selected);
596
682
 
597
683
  return SSL_TLSEXT_ERR_OK;
598
684
  }
685
+ #endif
599
686
 
600
687
  #ifdef HAVE_SSL_CTX_SET_NEXT_PROTO_SELECT_CB
601
688
  static int
602
- ssl_npn_advertise_cb(SSL *ssl, const unsigned char **out, unsigned int *outlen, void *arg)
689
+ ssl_npn_advertise_cb(SSL *ssl, const unsigned char **out, unsigned int *outlen,
690
+ void *arg)
603
691
  {
604
- VALUE sslctx_obj = (VALUE) arg;
605
- VALUE protocols = rb_iv_get(sslctx_obj, "@_protocols");
692
+ VALUE protocols = (VALUE)arg;
606
693
 
607
694
  *out = (const unsigned char *) RSTRING_PTR(protocols);
608
695
  *outlen = RSTRING_LENINT(protocols);
@@ -611,40 +698,40 @@ ssl_npn_advertise_cb(SSL *ssl, const unsigned char **out, unsigned int *outlen,
611
698
  }
612
699
 
613
700
  static int
614
- ssl_npn_select_cb(SSL *s, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg)
701
+ ssl_npn_select_cb(SSL *ssl, unsigned char **out, unsigned char *outlen,
702
+ const unsigned char *in, unsigned int inlen, void *arg)
615
703
  {
616
704
  VALUE sslctx_obj, cb;
617
705
 
618
706
  sslctx_obj = (VALUE) arg;
619
- cb = rb_iv_get(sslctx_obj, "@npn_select_cb");
707
+ cb = rb_attr_get(sslctx_obj, id_i_npn_select_cb);
620
708
 
621
- return ssl_npn_select_cb_common(cb, (const unsigned char **)out, outlen, in, inlen);
709
+ return ssl_npn_select_cb_common(ssl, cb, (const unsigned char **)out,
710
+ outlen, in, inlen);
622
711
  }
623
712
  #endif
624
713
 
625
714
  #ifdef HAVE_SSL_CTX_SET_ALPN_SELECT_CB
626
715
  static int
627
- ssl_alpn_select_cb(SSL *ssl, const unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg)
716
+ ssl_alpn_select_cb(SSL *ssl, const unsigned char **out, unsigned char *outlen,
717
+ const unsigned char *in, unsigned int inlen, void *arg)
628
718
  {
629
719
  VALUE sslctx_obj, cb;
630
720
 
631
721
  sslctx_obj = (VALUE) arg;
632
- cb = rb_iv_get(sslctx_obj, "@alpn_select_cb");
722
+ cb = rb_attr_get(sslctx_obj, id_i_alpn_select_cb);
633
723
 
634
- return ssl_npn_select_cb_common(cb, out, outlen, in, inlen);
724
+ return ssl_npn_select_cb_common(ssl, cb, out, outlen, in, inlen);
635
725
  }
636
726
  #endif
637
- #endif /* HAVE_SSL_CTX_SET_NEXT_PROTO_SELECT_CB || HAVE_SSL_CTX_SET_ALPN_SELECT_CB */
638
727
 
639
- /* This function may serve as the entry point to support further
640
- * callbacks. */
728
+ /* This function may serve as the entry point to support further callbacks. */
641
729
  static void
642
730
  ssl_info_cb(const SSL *ssl, int where, int val)
643
731
  {
644
- int state = SSL_state(ssl);
732
+ int is_server = SSL_is_server((SSL *)ssl);
645
733
 
646
- if ((where & SSL_CB_HANDSHAKE_START) &&
647
- (state & SSL_ST_ACCEPT)) {
734
+ if (is_server && where & SSL_CB_HANDSHAKE_START) {
648
735
  ssl_renegotiation_cb(ssl);
649
736
  }
650
737
  }
@@ -696,7 +783,6 @@ ossl_sslctx_setup(VALUE self)
696
783
  {
697
784
  SSL_CTX *ctx;
698
785
  X509 *cert = NULL, *client_ca = NULL;
699
- X509_STORE *store;
700
786
  EVP_PKEY *key = NULL;
701
787
  char *ca_path = NULL, *ca_file = NULL;
702
788
  int verify_mode;
@@ -711,34 +797,52 @@ ossl_sslctx_setup(VALUE self)
711
797
  #endif
712
798
 
713
799
  #if !defined(OPENSSL_NO_EC)
714
- if (RTEST(ossl_sslctx_get_tmp_ecdh_cb(self))){
800
+ /* We added SSLContext#tmp_ecdh_callback= in Ruby 2.3.0,
801
+ * but SSL_CTX_set_tmp_ecdh_callback() was removed in OpenSSL 1.1.0. */
802
+ if (RTEST(rb_attr_get(self, id_i_tmp_ecdh_callback))) {
803
+ # if defined(HAVE_SSL_CTX_SET_TMP_ECDH_CALLBACK)
804
+ rb_warn("#tmp_ecdh_callback= is deprecated; use #ecdh_curves= instead");
715
805
  SSL_CTX_set_tmp_ecdh_callback(ctx, ossl_tmp_ecdh_callback);
806
+ # if defined(HAVE_SSL_CTX_SET_ECDH_AUTO)
807
+ /* tmp_ecdh_callback and ecdh_auto conflict; OpenSSL ignores
808
+ * tmp_ecdh_callback. So disable ecdh_auto. */
809
+ if (!SSL_CTX_set_ecdh_auto(ctx, 0))
810
+ ossl_raise(eSSLError, "SSL_CTX_set_ecdh_auto");
811
+ # endif
812
+ # else
813
+ ossl_raise(eSSLError, "OpenSSL does not support tmp_ecdh_callback; "
814
+ "use #ecdh_curves= instead");
815
+ # endif
716
816
  }
717
- #endif
817
+ #endif /* OPENSSL_NO_EC */
718
818
 
719
- val = ossl_sslctx_get_cert_store(self);
720
- if(!NIL_P(val)){
819
+ val = rb_attr_get(self, id_i_cert_store);
820
+ if (!NIL_P(val)) {
821
+ X509_STORE *store = GetX509StorePtr(val); /* NO NEED TO DUP */
822
+ SSL_CTX_set_cert_store(ctx, store);
823
+ #if !defined(HAVE_X509_STORE_UP_REF)
721
824
  /*
722
825
  * WORKAROUND:
723
826
  * X509_STORE can count references, but
724
827
  * X509_STORE_free() doesn't care it.
725
828
  * So we won't increment it but mark it by ex_data.
726
829
  */
727
- store = GetX509StorePtr(val); /* NO NEED TO DUP */
728
- SSL_CTX_set_cert_store(ctx, store);
729
- SSL_CTX_set_ex_data(ctx, ossl_ssl_ex_store_p, (void*)1);
830
+ SSL_CTX_set_ex_data(ctx, ossl_ssl_ex_store_p, (void *)1);
831
+ #else /* Fixed in OpenSSL 1.0.2; bff9ce4db38b (master), 5b4b9ce976fc (1.0.2) */
832
+ X509_STORE_up_ref(store);
833
+ #endif
730
834
  }
731
835
 
732
- val = ossl_sslctx_get_extra_cert(self);
836
+ val = rb_attr_get(self, id_i_extra_chain_cert);
733
837
  if(!NIL_P(val)){
734
838
  rb_block_call(val, rb_intern("each"), 0, 0, ossl_sslctx_add_extra_chain_cert_i, self);
735
839
  }
736
840
 
737
841
  /* private key may be bundled in certificate file. */
738
- val = ossl_sslctx_get_cert(self);
842
+ val = rb_attr_get(self, id_i_cert);
739
843
  cert = NIL_P(val) ? NULL : GetX509CertPtr(val); /* NO DUP NEEDED */
740
- val = ossl_sslctx_get_key(self);
741
- key = NIL_P(val) ? NULL : GetPKeyPtr(val); /* NO DUP NEEDED */
844
+ val = rb_attr_get(self, id_i_key);
845
+ key = NIL_P(val) ? NULL : GetPrivPKeyPtr(val); /* NO DUP NEEDED */
742
846
  if (cert && key) {
743
847
  if (!SSL_CTX_use_certificate(ctx, cert)) {
744
848
  /* Adds a ref => Safe to FREE */
@@ -753,7 +857,7 @@ ossl_sslctx_setup(VALUE self)
753
857
  }
754
858
  }
755
859
 
756
- val = ossl_sslctx_get_client_ca(self);
860
+ val = rb_attr_get(self, id_i_client_ca);
757
861
  if(!NIL_P(val)){
758
862
  if (RB_TYPE_P(val, T_ARRAY)) {
759
863
  for(i = 0; i < RARRAY_LEN(val); i++){
@@ -773,48 +877,53 @@ ossl_sslctx_setup(VALUE self)
773
877
  }
774
878
  }
775
879
 
776
- val = ossl_sslctx_get_ca_file(self);
777
- ca_file = NIL_P(val) ? NULL : StringValuePtr(val);
778
- val = ossl_sslctx_get_ca_path(self);
779
- ca_path = NIL_P(val) ? NULL : StringValuePtr(val);
880
+ val = rb_attr_get(self, id_i_ca_file);
881
+ ca_file = NIL_P(val) ? NULL : StringValueCStr(val);
882
+ val = rb_attr_get(self, id_i_ca_path);
883
+ ca_path = NIL_P(val) ? NULL : StringValueCStr(val);
780
884
  if(ca_file || ca_path){
781
885
  if (!SSL_CTX_load_verify_locations(ctx, ca_file, ca_path))
782
886
  rb_warning("can't set verify locations");
783
887
  }
784
888
 
785
- val = ossl_sslctx_get_verify_mode(self);
889
+ val = rb_attr_get(self, id_i_verify_mode);
786
890
  verify_mode = NIL_P(val) ? SSL_VERIFY_NONE : NUM2INT(val);
787
891
  SSL_CTX_set_verify(ctx, verify_mode, ossl_ssl_verify_callback);
788
- if (RTEST(ossl_sslctx_get_client_cert_cb(self)))
892
+ if (RTEST(rb_attr_get(self, id_i_client_cert_cb)))
789
893
  SSL_CTX_set_client_cert_cb(ctx, ossl_client_cert_cb);
790
894
 
791
- val = ossl_sslctx_get_timeout(self);
895
+ val = rb_attr_get(self, id_i_timeout);
792
896
  if(!NIL_P(val)) SSL_CTX_set_timeout(ctx, NUM2LONG(val));
793
897
 
794
- val = ossl_sslctx_get_verify_dep(self);
898
+ val = rb_attr_get(self, id_i_verify_depth);
795
899
  if(!NIL_P(val)) SSL_CTX_set_verify_depth(ctx, NUM2INT(val));
796
900
 
797
901
  #ifdef HAVE_SSL_CTX_SET_NEXT_PROTO_SELECT_CB
798
- val = rb_iv_get(self, "@npn_protocols");
902
+ val = rb_attr_get(self, id_i_npn_protocols);
799
903
  if (!NIL_P(val)) {
800
- rb_iv_set(self, "@_protocols", ssl_encode_npn_protocols(val));
801
- SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_npn_advertise_cb, (void *) self);
904
+ VALUE encoded = ssl_encode_npn_protocols(val);
905
+ rb_ivar_set(self, id_npn_protocols_encoded, encoded);
906
+ SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_npn_advertise_cb, (void *)encoded);
802
907
  OSSL_Debug("SSL NPN advertise callback added");
803
908
  }
804
- if (RTEST(rb_iv_get(self, "@npn_select_cb"))) {
909
+ if (RTEST(rb_attr_get(self, id_i_npn_select_cb))) {
805
910
  SSL_CTX_set_next_proto_select_cb(ctx, ssl_npn_select_cb, (void *) self);
806
911
  OSSL_Debug("SSL NPN select callback added");
807
912
  }
808
913
  #endif
809
914
 
810
915
  #ifdef HAVE_SSL_CTX_SET_ALPN_SELECT_CB
811
- val = rb_iv_get(self, "@alpn_protocols");
916
+ val = rb_attr_get(self, id_i_alpn_protocols);
812
917
  if (!NIL_P(val)) {
813
918
  VALUE rprotos = ssl_encode_npn_protocols(val);
814
- SSL_CTX_set_alpn_protos(ctx, (const unsigned char *)StringValueCStr(rprotos), RSTRING_LENINT(rprotos));
919
+
920
+ /* returns 0 on success */
921
+ if (SSL_CTX_set_alpn_protos(ctx, (unsigned char *)RSTRING_PTR(rprotos),
922
+ RSTRING_LENINT(rprotos)))
923
+ ossl_raise(eSSLError, "SSL_CTX_set_alpn_protos");
815
924
  OSSL_Debug("SSL ALPN values added");
816
925
  }
817
- if (RTEST(rb_iv_get(self, "@alpn_select_cb"))) {
926
+ if (RTEST(rb_attr_get(self, id_i_alpn_select_cb))) {
818
927
  SSL_CTX_set_alpn_select_cb(ctx, ssl_alpn_select_cb, (void *) self);
819
928
  OSSL_Debug("SSL ALPN select callback added");
820
929
  }
@@ -822,7 +931,7 @@ ossl_sslctx_setup(VALUE self)
822
931
 
823
932
  rb_obj_freeze(self);
824
933
 
825
- val = ossl_sslctx_get_sess_id_ctx(self);
934
+ val = rb_attr_get(self, id_i_session_id_context);
826
935
  if (!NIL_P(val)){
827
936
  StringValue(val);
828
937
  if (!SSL_CTX_set_session_id_context(ctx, (unsigned char *)RSTRING_PTR(val),
@@ -831,21 +940,21 @@ ossl_sslctx_setup(VALUE self)
831
940
  }
832
941
  }
833
942
 
834
- if (RTEST(rb_iv_get(self, "@session_get_cb"))) {
943
+ if (RTEST(rb_attr_get(self, id_i_session_get_cb))) {
835
944
  SSL_CTX_sess_set_get_cb(ctx, ossl_sslctx_session_get_cb);
836
945
  OSSL_Debug("SSL SESSION get callback added");
837
946
  }
838
- if (RTEST(rb_iv_get(self, "@session_new_cb"))) {
947
+ if (RTEST(rb_attr_get(self, id_i_session_new_cb))) {
839
948
  SSL_CTX_sess_set_new_cb(ctx, ossl_sslctx_session_new_cb);
840
949
  OSSL_Debug("SSL SESSION new callback added");
841
950
  }
842
- if (RTEST(rb_iv_get(self, "@session_remove_cb"))) {
951
+ if (RTEST(rb_attr_get(self, id_i_session_remove_cb))) {
843
952
  SSL_CTX_sess_set_remove_cb(ctx, ossl_sslctx_session_remove_cb);
844
953
  OSSL_Debug("SSL SESSION remove callback added");
845
954
  }
846
955
 
847
956
  #ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME
848
- val = rb_iv_get(self, "@servername_cb");
957
+ val = rb_attr_get(self, id_i_servername_cb);
849
958
  if (!NIL_P(val)) {
850
959
  SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb);
851
960
  OSSL_Debug("SSL TLSEXT servername callback added");
@@ -856,7 +965,7 @@ ossl_sslctx_setup(VALUE self)
856
965
  }
857
966
 
858
967
  static VALUE
859
- ossl_ssl_cipher_to_ary(SSL_CIPHER *cipher)
968
+ ossl_ssl_cipher_to_ary(const SSL_CIPHER *cipher)
860
969
  {
861
970
  VALUE ary;
862
971
  int bits, alg_bits;
@@ -865,8 +974,8 @@ ossl_ssl_cipher_to_ary(SSL_CIPHER *cipher)
865
974
  rb_ary_push(ary, rb_str_new2(SSL_CIPHER_get_name(cipher)));
866
975
  rb_ary_push(ary, rb_str_new2(SSL_CIPHER_get_version(cipher)));
867
976
  bits = SSL_CIPHER_get_bits(cipher, &alg_bits);
868
- rb_ary_push(ary, INT2FIX(bits));
869
- rb_ary_push(ary, INT2FIX(alg_bits));
977
+ rb_ary_push(ary, INT2NUM(bits));
978
+ rb_ary_push(ary, INT2NUM(alg_bits));
870
979
 
871
980
  return ary;
872
981
  }
@@ -875,24 +984,19 @@ ossl_ssl_cipher_to_ary(SSL_CIPHER *cipher)
875
984
  * call-seq:
876
985
  * ctx.ciphers => [[name, version, bits, alg_bits], ...]
877
986
  *
878
- * The list of ciphers configured for this context.
987
+ * The list of cipher suites configured for this context.
879
988
  */
880
989
  static VALUE
881
990
  ossl_sslctx_get_ciphers(VALUE self)
882
991
  {
883
992
  SSL_CTX *ctx;
884
993
  STACK_OF(SSL_CIPHER) *ciphers;
885
- SSL_CIPHER *cipher;
994
+ const SSL_CIPHER *cipher;
886
995
  VALUE ary;
887
996
  int i, num;
888
997
 
889
998
  GetSSLCTX(self, ctx);
890
- if(!ctx){
891
- rb_warning("SSL_CTX is not initialized.");
892
- return Qnil;
893
- }
894
- ciphers = ctx->cipher_list;
895
-
999
+ ciphers = SSL_CTX_get_ciphers(ctx);
896
1000
  if (!ciphers)
897
1001
  return rb_ary_new();
898
1002
 
@@ -911,11 +1015,9 @@ ossl_sslctx_get_ciphers(VALUE self)
911
1015
  * ctx.ciphers = [name, ...]
912
1016
  * ctx.ciphers = [[name, version, bits, alg_bits], ...]
913
1017
  *
914
- * Sets the list of available ciphers for this context. Note in a server
1018
+ * Sets the list of available cipher suites for this context. Note in a server
915
1019
  * context some ciphers require the appropriate certificates. For example, an
916
- * RSA cipher can only be chosen when an RSA certificate is available.
917
- *
918
- * See also OpenSSL::Cipher and OpenSSL::Cipher::ciphers
1020
+ * RSA cipher suite can only be chosen when an RSA certificate is available.
919
1021
  */
920
1022
  static VALUE
921
1023
  ossl_sslctx_set_ciphers(VALUE self, VALUE v)
@@ -942,22 +1044,165 @@ ossl_sslctx_set_ciphers(VALUE self, VALUE v)
942
1044
  }
943
1045
 
944
1046
  GetSSLCTX(self, ctx);
945
- if(!ctx){
946
- ossl_raise(eSSLError, "SSL_CTX is not initialized.");
947
- return Qnil;
948
- }
949
- if (!SSL_CTX_set_cipher_list(ctx, RSTRING_PTR(str))) {
1047
+ if (!SSL_CTX_set_cipher_list(ctx, StringValueCStr(str))) {
950
1048
  ossl_raise(eSSLError, "SSL_CTX_set_cipher_list");
951
1049
  }
952
1050
 
953
1051
  return v;
954
1052
  }
955
1053
 
1054
+ #if !defined(OPENSSL_NO_EC)
1055
+ /*
1056
+ * call-seq:
1057
+ * ctx.ecdh_curves = curve_list -> curve_list
1058
+ *
1059
+ * Sets the list of "supported elliptic curves" for this context.
1060
+ *
1061
+ * For a TLS client, the list is directly used in the Supported Elliptic Curves
1062
+ * Extension. For a server, the list is used by OpenSSL to determine the set of
1063
+ * shared curves. OpenSSL will pick the most appropriate one from it.
1064
+ *
1065
+ * Note that this works differently with old OpenSSL (<= 1.0.1). Only one curve
1066
+ * can be set, and this has no effect for TLS clients.
1067
+ *
1068
+ * === Example
1069
+ * ctx1 = OpenSSL::SSL::SSLContext.new
1070
+ * ctx1.ecdh_curves = "X25519:P-256:P-224"
1071
+ * svr = OpenSSL::SSL::SSLServer.new(tcp_svr, ctx1)
1072
+ * Thread.new { svr.accept }
1073
+ *
1074
+ * ctx2 = OpenSSL::SSL::SSLContext.new
1075
+ * ctx2.ecdh_curves = "P-256"
1076
+ * cli = OpenSSL::SSL::SSLSocket.new(tcp_sock, ctx2)
1077
+ * cli.connect
1078
+ *
1079
+ * p cli.tmp_key.group.curve_name
1080
+ * # => "prime256v1" (is an alias for NIST P-256)
1081
+ */
1082
+ static VALUE
1083
+ ossl_sslctx_set_ecdh_curves(VALUE self, VALUE arg)
1084
+ {
1085
+ SSL_CTX *ctx;
1086
+
1087
+ rb_check_frozen(self);
1088
+ GetSSLCTX(self, ctx);
1089
+ StringValueCStr(arg);
1090
+
1091
+ #if defined(HAVE_SSL_CTX_SET1_CURVES_LIST)
1092
+ if (!SSL_CTX_set1_curves_list(ctx, RSTRING_PTR(arg)))
1093
+ ossl_raise(eSSLError, NULL);
1094
+ #else
1095
+ /* OpenSSL does not have SSL_CTX_set1_curves_list()... Fallback to
1096
+ * SSL_CTX_set_tmp_ecdh(). So only the first curve is used. */
1097
+ {
1098
+ VALUE curve, splitted;
1099
+ EC_KEY *ec;
1100
+ int nid;
1101
+
1102
+ splitted = rb_str_split(arg, ":");
1103
+ if (!RARRAY_LEN(splitted))
1104
+ ossl_raise(eSSLError, "invalid input format");
1105
+ curve = RARRAY_AREF(splitted, 0);
1106
+ StringValueCStr(curve);
1107
+
1108
+ /* SSL_CTX_set1_curves_list() accepts NIST names */
1109
+ nid = EC_curve_nist2nid(RSTRING_PTR(curve));
1110
+ if (nid == NID_undef)
1111
+ nid = OBJ_txt2nid(RSTRING_PTR(curve));
1112
+ if (nid == NID_undef)
1113
+ ossl_raise(eSSLError, "unknown curve name");
1114
+
1115
+ ec = EC_KEY_new_by_curve_name(nid);
1116
+ if (!ec)
1117
+ ossl_raise(eSSLError, NULL);
1118
+ EC_KEY_set_asn1_flag(ec, OPENSSL_EC_NAMED_CURVE);
1119
+ if (!SSL_CTX_set_tmp_ecdh(ctx, ec)) {
1120
+ EC_KEY_free(ec);
1121
+ ossl_raise(eSSLError, "SSL_CTX_set_tmp_ecdh");
1122
+ }
1123
+ EC_KEY_free(ec);
1124
+ # if defined(HAVE_SSL_CTX_SET_ECDH_AUTO)
1125
+ /* tmp_ecdh and ecdh_auto conflict. tmp_ecdh is ignored when ecdh_auto
1126
+ * is enabled. So disable ecdh_auto. */
1127
+ if (!SSL_CTX_set_ecdh_auto(ctx, 0))
1128
+ ossl_raise(eSSLError, "SSL_CTX_set_ecdh_auto");
1129
+ # endif
1130
+ }
1131
+ #endif
1132
+
1133
+ return arg;
1134
+ }
1135
+ #else
1136
+ #define ossl_sslctx_set_ecdh_curves rb_f_notimplement
1137
+ #endif
1138
+
1139
+ /*
1140
+ * call-seq:
1141
+ * ctx.security_level -> Integer
1142
+ *
1143
+ * Returns the security level for the context.
1144
+ *
1145
+ * See also OpenSSL::SSL::SSLContext#security_level=.
1146
+ */
1147
+ static VALUE
1148
+ ossl_sslctx_get_security_level(VALUE self)
1149
+ {
1150
+ SSL_CTX *ctx;
1151
+
1152
+ GetSSLCTX(self, ctx);
1153
+
1154
+ #if defined(HAVE_SSL_CTX_GET_SECURITY_LEVEL)
1155
+ return INT2NUM(SSL_CTX_get_security_level(ctx));
1156
+ #else
1157
+ (void)ctx;
1158
+ return INT2FIX(0);
1159
+ #endif
1160
+ }
1161
+
1162
+ /*
1163
+ * call-seq:
1164
+ * ctx.security_level = integer
1165
+ *
1166
+ * Sets the security level for the context. OpenSSL limits parameters according
1167
+ * to the level. The "parameters" include: ciphersuites, curves, key sizes,
1168
+ * certificate signature algorithms, protocol version and so on. For example,
1169
+ * level 1 rejects parameters offering below 80 bits of security, such as
1170
+ * ciphersuites using MD5 for the MAC or RSA keys shorter than 1024 bits.
1171
+ *
1172
+ * Note that attempts to set such parameters with insufficient security are
1173
+ * also blocked. You need to lower the level first.
1174
+ *
1175
+ * This feature is not supported in OpenSSL < 1.1.0, and setting the level to
1176
+ * other than 0 will raise NotImplementedError. Level 0 means everything is
1177
+ * permitted, the same behavior as previous versions of OpenSSL.
1178
+ *
1179
+ * See the manpage of SSL_CTX_set_security_level(3) for details.
1180
+ */
1181
+ static VALUE
1182
+ ossl_sslctx_set_security_level(VALUE self, VALUE value)
1183
+ {
1184
+ SSL_CTX *ctx;
1185
+
1186
+ rb_check_frozen(self);
1187
+ GetSSLCTX(self, ctx);
1188
+
1189
+ #if defined(HAVE_SSL_CTX_GET_SECURITY_LEVEL)
1190
+ SSL_CTX_set_security_level(ctx, NUM2INT(value));
1191
+ #else
1192
+ (void)ctx;
1193
+ if (NUM2INT(value) != 0)
1194
+ ossl_raise(rb_eNotImpError, "setting security level to other than 0 is "
1195
+ "not supported in this version of OpenSSL");
1196
+ #endif
1197
+
1198
+ return value;
1199
+ }
1200
+
956
1201
  /*
957
1202
  * call-seq:
958
1203
  * ctx.session_add(session) -> true | false
959
1204
  *
960
- * Adds +session+ to the session cache
1205
+ * Adds +session+ to the session cache.
961
1206
  */
962
1207
  static VALUE
963
1208
  ossl_sslctx_session_add(VALUE self, VALUE arg)
@@ -975,7 +1220,7 @@ ossl_sslctx_session_add(VALUE self, VALUE arg)
975
1220
  * call-seq:
976
1221
  * ctx.session_remove(session) -> true | false
977
1222
  *
978
- * Removes +session+ from the session cache
1223
+ * Removes +session+ from the session cache.
979
1224
  */
980
1225
  static VALUE
981
1226
  ossl_sslctx_session_remove(VALUE self, VALUE arg)
@@ -1143,25 +1388,11 @@ ossl_sslctx_flush_sessions(int argc, VALUE *argv, VALUE self)
1143
1388
  * SSLSocket class
1144
1389
  */
1145
1390
  #ifndef OPENSSL_NO_SOCK
1146
- static void
1147
- ossl_ssl_shutdown(SSL *ssl)
1148
- {
1149
- int i, rc;
1150
-
1151
- if (ssl) {
1152
- /* 4 is from SSL_smart_shutdown() of mod_ssl.c (v2.2.19) */
1153
- /* It says max 2x pending + 2x data = 4 */
1154
- for (i = 0; i < 4; ++i) {
1155
- /*
1156
- * Ignore the case SSL_shutdown returns -1. Empty handshake_func
1157
- * must not happen.
1158
- */
1159
- if ((rc = SSL_shutdown(ssl)) != 0)
1160
- break;
1161
- }
1162
- SSL_clear(ssl);
1163
- ERR_clear_error();
1164
- }
1391
+ static inline int
1392
+ ssl_started(SSL *ssl)
1393
+ {
1394
+ /* the FD is set in ossl_ssl_setup(), called by #connect or #accept */
1395
+ return SSL_get_fd(ssl) >= 0;
1165
1396
  }
1166
1397
 
1167
1398
  static void
@@ -1184,45 +1415,76 @@ ossl_ssl_s_alloc(VALUE klass)
1184
1415
  return TypedData_Wrap_Struct(klass, &ossl_ssl_type, NULL);
1185
1416
  }
1186
1417
 
1418
+ /*
1419
+ * call-seq:
1420
+ * SSLSocket.new(io) => aSSLSocket
1421
+ * SSLSocket.new(io, ctx) => aSSLSocket
1422
+ *
1423
+ * Creates a new SSL socket from +io+ which must be a real IO object (not an
1424
+ * IO-like object that responds to read/write).
1425
+ *
1426
+ * If +ctx+ is provided the SSL Sockets initial params will be taken from
1427
+ * the context.
1428
+ *
1429
+ * The OpenSSL::Buffering module provides additional IO methods.
1430
+ *
1431
+ * This method will freeze the SSLContext if one is provided;
1432
+ * however, session management is still allowed in the frozen SSLContext.
1433
+ */
1187
1434
  static VALUE
1188
- ossl_ssl_setup(VALUE self)
1435
+ ossl_ssl_initialize(int argc, VALUE *argv, VALUE self)
1189
1436
  {
1190
- VALUE io, v_ctx, cb;
1437
+ VALUE io, v_ctx, verify_cb;
1438
+ SSL *ssl;
1191
1439
  SSL_CTX *ctx;
1440
+
1441
+ TypedData_Get_Struct(self, SSL, &ossl_ssl_type, ssl);
1442
+ if (ssl)
1443
+ ossl_raise(eSSLError, "SSL already initialized");
1444
+
1445
+ if (rb_scan_args(argc, argv, "11", &io, &v_ctx) == 1)
1446
+ v_ctx = rb_funcall(cSSLContext, rb_intern("new"), 0);
1447
+
1448
+ GetSSLCTX(v_ctx, ctx);
1449
+ rb_ivar_set(self, id_i_context, v_ctx);
1450
+ ossl_sslctx_setup(v_ctx);
1451
+
1452
+ if (rb_respond_to(io, rb_intern("nonblock=")))
1453
+ rb_funcall(io, rb_intern("nonblock="), 1, Qtrue);
1454
+ rb_ivar_set(self, id_i_io, io);
1455
+
1456
+ ssl = SSL_new(ctx);
1457
+ if (!ssl)
1458
+ ossl_raise(eSSLError, NULL);
1459
+ RTYPEDDATA_DATA(self) = ssl;
1460
+
1461
+ SSL_set_ex_data(ssl, ossl_ssl_ex_ptr_idx, (void *)self);
1462
+ SSL_set_info_callback(ssl, ssl_info_cb);
1463
+ verify_cb = rb_attr_get(v_ctx, id_i_verify_callback);
1464
+ SSL_set_ex_data(ssl, ossl_ssl_ex_vcb_idx, (void *)verify_cb);
1465
+
1466
+ rb_call_super(0, NULL);
1467
+
1468
+ return self;
1469
+ }
1470
+
1471
+ static VALUE
1472
+ ossl_ssl_setup(VALUE self)
1473
+ {
1474
+ VALUE io;
1192
1475
  SSL *ssl;
1193
1476
  rb_io_t *fptr;
1194
1477
 
1195
1478
  GetSSL(self, ssl);
1196
- if(!ssl){
1197
- #ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME
1198
- VALUE hostname = rb_iv_get(self, "@hostname");
1199
- #endif
1479
+ if (ssl_started(ssl))
1480
+ return Qtrue;
1200
1481
 
1201
- v_ctx = ossl_ssl_get_ctx(self);
1202
- GetSSLCTX(v_ctx, ctx);
1203
-
1204
- ssl = SSL_new(ctx);
1205
- if (!ssl) {
1206
- ossl_raise(eSSLError, "SSL_new");
1207
- }
1208
- DATA_PTR(self) = ssl;
1209
-
1210
- #ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME
1211
- if (!NIL_P(hostname)) {
1212
- if (SSL_set_tlsext_host_name(ssl, StringValuePtr(hostname)) != 1)
1213
- ossl_raise(eSSLError, "SSL_set_tlsext_host_name");
1214
- }
1215
- #endif
1216
- io = ossl_ssl_get_io(self);
1217
- GetOpenFile(io, fptr);
1218
- rb_io_check_readable(fptr);
1219
- rb_io_check_writable(fptr);
1220
- SSL_set_fd(ssl, TO_SOCKET(FPTR_TO_FD(fptr)));
1221
- SSL_set_ex_data(ssl, ossl_ssl_ex_ptr_idx, (void*)self);
1222
- cb = ossl_sslctx_get_verify_cb(v_ctx);
1223
- SSL_set_ex_data(ssl, ossl_ssl_ex_vcb_idx, (void*)cb);
1224
- SSL_set_info_callback(ssl, ssl_info_cb);
1225
- }
1482
+ io = rb_attr_get(self, id_i_io);
1483
+ GetOpenFile(io, fptr);
1484
+ rb_io_check_readable(fptr);
1485
+ rb_io_check_writable(fptr);
1486
+ if (!SSL_set_fd(ssl, TO_SOCKET(FPTR_TO_FD(fptr))))
1487
+ ossl_raise(eSSLError, "SSL_set_fd");
1226
1488
 
1227
1489
  return Qtrue;
1228
1490
  }
@@ -1233,31 +1495,18 @@ ossl_ssl_setup(VALUE self)
1233
1495
  #define ssl_get_error(ssl, ret) SSL_get_error((ssl), (ret))
1234
1496
  #endif
1235
1497
 
1236
- #define ossl_ssl_data_get_struct(v, ssl) \
1237
- do { \
1238
- GetSSL((v), (ssl)); \
1239
- if (!(ssl)) { \
1240
- rb_warning("SSL session is not started yet."); \
1241
- return Qnil; \
1242
- } \
1243
- } while (0)
1244
-
1245
1498
  static void
1246
1499
  write_would_block(int nonblock)
1247
1500
  {
1248
- if (nonblock) {
1249
- VALUE exc = ossl_exc_new(eSSLErrorWaitWritable, "write would block");
1250
- rb_exc_raise(exc);
1251
- }
1501
+ if (nonblock)
1502
+ ossl_raise(eSSLErrorWaitWritable, "write would block");
1252
1503
  }
1253
1504
 
1254
1505
  static void
1255
1506
  read_would_block(int nonblock)
1256
1507
  {
1257
- if (nonblock) {
1258
- VALUE exc = ossl_exc_new(eSSLErrorWaitReadable, "read would block");
1259
- rb_exc_raise(exc);
1260
- }
1508
+ if (nonblock)
1509
+ ossl_raise(eSSLErrorWaitReadable, "read would block");
1261
1510
  }
1262
1511
 
1263
1512
  static int
@@ -1280,15 +1529,18 @@ ossl_start_ssl(VALUE self, int (*func)(), const char *funcname, VALUE opts)
1280
1529
 
1281
1530
  rb_ivar_set(self, ID_callback_state, Qnil);
1282
1531
 
1283
- ossl_ssl_data_get_struct(self, ssl);
1532
+ GetSSL(self, ssl);
1284
1533
 
1285
- GetOpenFile(ossl_ssl_get_io(self), fptr);
1534
+ GetOpenFile(rb_attr_get(self, id_i_io), fptr);
1286
1535
  for(;;){
1287
1536
  ret = func(ssl);
1288
1537
 
1289
- cb_state = rb_ivar_get(self, ID_callback_state);
1290
- if (!NIL_P(cb_state))
1291
- rb_jump_tag(NUM2INT(cb_state));
1538
+ cb_state = rb_attr_get(self, ID_callback_state);
1539
+ if (!NIL_P(cb_state)) {
1540
+ /* must cleanup OpenSSL error stack before re-raising */
1541
+ ossl_clear_error();
1542
+ rb_jump_tag(NUM2INT(cb_state));
1543
+ }
1292
1544
 
1293
1545
  if (ret > 0)
1294
1546
  break;
@@ -1418,7 +1670,7 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
1418
1670
  int ilen, nread = 0;
1419
1671
  VALUE len, str;
1420
1672
  rb_io_t *fptr;
1421
- VALUE opts = Qnil;
1673
+ VALUE io, opts = Qnil;
1422
1674
 
1423
1675
  if (nonblock) {
1424
1676
  rb_scan_args(argc, argv, "11:", &len, &str, &opts);
@@ -1427,21 +1679,26 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
1427
1679
  }
1428
1680
 
1429
1681
  ilen = NUM2INT(len);
1430
- if(NIL_P(str)) str = rb_str_new(0, ilen);
1431
- else{
1432
- StringValue(str);
1433
- rb_str_modify(str);
1434
- rb_str_resize(str, ilen);
1682
+ if (NIL_P(str))
1683
+ str = rb_str_new(0, ilen);
1684
+ else {
1685
+ StringValue(str);
1686
+ if (RSTRING_LEN(str) >= ilen)
1687
+ rb_str_modify(str);
1688
+ else
1689
+ rb_str_modify_expand(str, ilen - RSTRING_LEN(str));
1435
1690
  }
1436
- if(ilen == 0) return str;
1691
+ OBJ_TAINT(str);
1692
+ rb_str_set_len(str, 0);
1693
+ if (ilen == 0)
1694
+ return str;
1437
1695
 
1438
1696
  GetSSL(self, ssl);
1439
- GetOpenFile(ossl_ssl_get_io(self), fptr);
1440
- if (ssl) {
1441
- if(!nonblock && SSL_pending(ssl) <= 0)
1442
- rb_thread_wait_fd(FPTR_TO_FD(fptr));
1697
+ io = rb_attr_get(self, id_i_io);
1698
+ GetOpenFile(io, fptr);
1699
+ if (ssl_started(ssl)) {
1443
1700
  for (;;){
1444
- nread = SSL_read(ssl, RSTRING_PTR(str), RSTRING_LENINT(str));
1701
+ nread = SSL_read(ssl, RSTRING_PTR(str), ilen);
1445
1702
  switch(ssl_get_error(ssl, nread)){
1446
1703
  case SSL_ERROR_NONE:
1447
1704
  goto end;
@@ -1459,30 +1716,38 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
1459
1716
  rb_io_wait_readable(FPTR_TO_FD(fptr));
1460
1717
  continue;
1461
1718
  case SSL_ERROR_SYSCALL:
1462
- if(ERR_peek_error() == 0 && nread == 0) {
1463
- if (no_exception_p(opts)) { return Qnil; }
1464
- rb_eof_error();
1719
+ if (!ERR_peek_error()) {
1720
+ if (errno)
1721
+ rb_sys_fail(0);
1722
+ else {
1723
+ /*
1724
+ * The underlying BIO returned 0. This is actually a
1725
+ * protocol error. But unfortunately, not all
1726
+ * implementations cleanly shutdown the TLS connection
1727
+ * but just shutdown/close the TCP connection. So report
1728
+ * EOF for now...
1729
+ */
1730
+ if (no_exception_p(opts)) { return Qnil; }
1731
+ rb_eof_error();
1732
+ }
1465
1733
  }
1466
- rb_sys_fail(0);
1467
1734
  default:
1468
1735
  ossl_raise(eSSLError, "SSL_read");
1469
1736
  }
1470
1737
  }
1471
1738
  }
1472
1739
  else {
1473
- ID meth = nonblock ? rb_intern("read_nonblock") : rb_intern("sysread");
1474
- rb_warning("SSL session is not started yet.");
1475
- if (nonblock) {
1476
- return rb_funcall(ossl_ssl_get_io(self), meth, 3, len, str, opts);
1477
- } else {
1478
- return rb_funcall(ossl_ssl_get_io(self), meth, 2, len, str);
1479
- }
1740
+ ID meth = nonblock ? rb_intern("read_nonblock") : rb_intern("sysread");
1741
+
1742
+ rb_warning("SSL session is not started yet.");
1743
+ if (nonblock)
1744
+ return rb_funcall(io, meth, 3, len, str, opts);
1745
+ else
1746
+ return rb_funcall(io, meth, 2, len, str);
1480
1747
  }
1481
1748
 
1482
1749
  end:
1483
1750
  rb_str_set_len(str, nread);
1484
- OBJ_TAINT(str);
1485
-
1486
1751
  return str;
1487
1752
  }
1488
1753
 
@@ -1526,12 +1791,13 @@ ossl_ssl_write_internal(VALUE self, VALUE str, VALUE opts)
1526
1791
  int nwrite = 0;
1527
1792
  rb_io_t *fptr;
1528
1793
  int nonblock = opts != Qfalse;
1794
+ VALUE io;
1529
1795
 
1530
1796
  StringValue(str);
1531
1797
  GetSSL(self, ssl);
1532
- GetOpenFile(ossl_ssl_get_io(self), fptr);
1533
-
1534
- if (ssl) {
1798
+ io = rb_attr_get(self, id_i_io);
1799
+ GetOpenFile(io, fptr);
1800
+ if (ssl_started(ssl)) {
1535
1801
  for (;;){
1536
1802
  int num = RSTRING_LENINT(str);
1537
1803
 
@@ -1561,9 +1827,14 @@ ossl_ssl_write_internal(VALUE self, VALUE str, VALUE opts)
1561
1827
  }
1562
1828
  }
1563
1829
  else {
1564
- ID id_syswrite = rb_intern("syswrite");
1565
- rb_warning("SSL session is not started yet.");
1566
- return rb_funcall(ossl_ssl_get_io(self), id_syswrite, 1, str);
1830
+ ID meth = nonblock ?
1831
+ rb_intern("write_nonblock") : rb_intern("syswrite");
1832
+
1833
+ rb_warning("SSL session is not started yet.");
1834
+ if (nonblock)
1835
+ return rb_funcall(io, meth, 2, str, opts);
1836
+ else
1837
+ return rb_funcall(io, meth, 1, str);
1567
1838
  }
1568
1839
 
1569
1840
  end:
@@ -1610,11 +1881,24 @@ static VALUE
1610
1881
  ossl_ssl_stop(VALUE self)
1611
1882
  {
1612
1883
  SSL *ssl;
1884
+ int ret;
1613
1885
 
1614
- ossl_ssl_data_get_struct(self, ssl);
1615
-
1616
- ossl_ssl_shutdown(ssl);
1886
+ GetSSL(self, ssl);
1887
+ if (!ssl_started(ssl))
1888
+ return Qnil;
1889
+ ret = SSL_shutdown(ssl);
1890
+ if (ret == 1) /* Have already received close_notify */
1891
+ return Qnil;
1892
+ if (ret == 0) /* Sent close_notify, but we don't wait for reply */
1893
+ return Qnil;
1617
1894
 
1895
+ /*
1896
+ * XXX: Something happened. Possibly it failed because the underlying socket
1897
+ * is not writable/readable, since it is in non-blocking mode. We should do
1898
+ * some proper error handling using SSL_get_error() and maybe retry, but we
1899
+ * can't block here. Give up for now.
1900
+ */
1901
+ ossl_clear_error();
1618
1902
  return Qnil;
1619
1903
  }
1620
1904
 
@@ -1630,7 +1914,7 @@ ossl_ssl_get_cert(VALUE self)
1630
1914
  SSL *ssl;
1631
1915
  X509 *cert = NULL;
1632
1916
 
1633
- ossl_ssl_data_get_struct(self, ssl);
1917
+ GetSSL(self, ssl);
1634
1918
 
1635
1919
  /*
1636
1920
  * Is this OpenSSL bug? Should add a ref?
@@ -1657,7 +1941,7 @@ ossl_ssl_get_peer_cert(VALUE self)
1657
1941
  X509 *cert = NULL;
1658
1942
  VALUE obj;
1659
1943
 
1660
- ossl_ssl_data_get_struct(self, ssl);
1944
+ GetSSL(self, ssl);
1661
1945
 
1662
1946
  cert = SSL_get_peer_certificate(ssl); /* Adds a ref => Safe to FREE. */
1663
1947
 
@@ -1685,7 +1969,7 @@ ossl_ssl_get_peer_cert_chain(VALUE self)
1685
1969
  VALUE ary;
1686
1970
  int i, num;
1687
1971
 
1688
- ossl_ssl_data_get_struct(self, ssl);
1972
+ GetSSL(self, ssl);
1689
1973
 
1690
1974
  chain = SSL_get_peer_cert_chain(ssl);
1691
1975
  if(!chain) return Qnil;
@@ -1711,7 +1995,7 @@ ossl_ssl_get_version(VALUE self)
1711
1995
  {
1712
1996
  SSL *ssl;
1713
1997
 
1714
- ossl_ssl_data_get_struct(self, ssl);
1998
+ GetSSL(self, ssl);
1715
1999
 
1716
2000
  return rb_str_new2(SSL_get_version(ssl));
1717
2001
  }
@@ -1728,7 +2012,7 @@ ossl_ssl_get_cipher(VALUE self)
1728
2012
  SSL *ssl;
1729
2013
  SSL_CIPHER *cipher;
1730
2014
 
1731
- ossl_ssl_data_get_struct(self, ssl);
2015
+ GetSSL(self, ssl);
1732
2016
 
1733
2017
  cipher = (SSL_CIPHER *)SSL_get_current_cipher(ssl);
1734
2018
 
@@ -1739,7 +2023,8 @@ ossl_ssl_get_cipher(VALUE self)
1739
2023
  * call-seq:
1740
2024
  * ssl.state => string
1741
2025
  *
1742
- * A description of the current connection state.
2026
+ * A description of the current connection state. This is for diagnostic
2027
+ * purposes only.
1743
2028
  */
1744
2029
  static VALUE
1745
2030
  ossl_ssl_get_state(VALUE self)
@@ -1747,7 +2032,7 @@ ossl_ssl_get_state(VALUE self)
1747
2032
  SSL *ssl;
1748
2033
  VALUE ret;
1749
2034
 
1750
- ossl_ssl_data_get_struct(self, ssl);
2035
+ GetSSL(self, ssl);
1751
2036
 
1752
2037
  ret = rb_str_new2(SSL_state_string(ssl));
1753
2038
  if (ruby_verbose) {
@@ -1761,14 +2046,14 @@ ossl_ssl_get_state(VALUE self)
1761
2046
  * call-seq:
1762
2047
  * ssl.pending => Integer
1763
2048
  *
1764
- * The number of bytes that are immediately available for reading
2049
+ * The number of bytes that are immediately available for reading.
1765
2050
  */
1766
2051
  static VALUE
1767
2052
  ossl_ssl_pending(VALUE self)
1768
2053
  {
1769
2054
  SSL *ssl;
1770
2055
 
1771
- ossl_ssl_data_get_struct(self, ssl);
2056
+ GetSSL(self, ssl);
1772
2057
 
1773
2058
  return INT2NUM(SSL_pending(ssl));
1774
2059
  }
@@ -1784,15 +2069,9 @@ ossl_ssl_session_reused(VALUE self)
1784
2069
  {
1785
2070
  SSL *ssl;
1786
2071
 
1787
- ossl_ssl_data_get_struct(self, ssl);
1788
-
1789
- switch(SSL_session_reused(ssl)) {
1790
- case 1: return Qtrue;
1791
- case 0: return Qfalse;
1792
- default: ossl_raise(eSSLError, "SSL_session_reused");
1793
- }
2072
+ GetSSL(self, ssl);
1794
2073
 
1795
- UNREACHABLE;
2074
+ return SSL_session_reused(ssl) ? Qtrue : Qfalse;
1796
2075
  }
1797
2076
 
1798
2077
  /*
@@ -1807,11 +2086,7 @@ ossl_ssl_set_session(VALUE self, VALUE arg1)
1807
2086
  SSL *ssl;
1808
2087
  SSL_SESSION *sess;
1809
2088
 
1810
- /* why is ossl_ssl_setup delayed? */
1811
- ossl_ssl_setup(self);
1812
-
1813
- ossl_ssl_data_get_struct(self, ssl);
1814
-
2089
+ GetSSL(self, ssl);
1815
2090
  SafeGetSSLSession(arg1, sess);
1816
2091
 
1817
2092
  if (SSL_set_session(ssl, sess) != 1)
@@ -1820,6 +2095,35 @@ ossl_ssl_set_session(VALUE self, VALUE arg1)
1820
2095
  return arg1;
1821
2096
  }
1822
2097
 
2098
+ #ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME
2099
+ /*
2100
+ * call-seq:
2101
+ * ssl.hostname = hostname -> hostname
2102
+ *
2103
+ * Sets the server hostname used for SNI. This needs to be set before
2104
+ * SSLSocket#connect.
2105
+ */
2106
+ static VALUE
2107
+ ossl_ssl_set_hostname(VALUE self, VALUE arg)
2108
+ {
2109
+ SSL *ssl;
2110
+ char *hostname = NULL;
2111
+
2112
+ GetSSL(self, ssl);
2113
+
2114
+ if (!NIL_P(arg))
2115
+ hostname = StringValueCStr(arg);
2116
+
2117
+ if (!SSL_set_tlsext_host_name(ssl, hostname))
2118
+ ossl_raise(eSSLError, NULL);
2119
+
2120
+ /* for SSLSocket#hostname */
2121
+ rb_ivar_set(self, id_i_hostname, arg);
2122
+
2123
+ return arg;
2124
+ }
2125
+ #endif
2126
+
1823
2127
  /*
1824
2128
  * call-seq:
1825
2129
  * ssl.verify_result => Integer
@@ -1834,9 +2138,9 @@ ossl_ssl_get_verify_result(VALUE self)
1834
2138
  {
1835
2139
  SSL *ssl;
1836
2140
 
1837
- ossl_ssl_data_get_struct(self, ssl);
2141
+ GetSSL(self, ssl);
1838
2142
 
1839
- return INT2FIX(SSL_get_verify_result(ssl));
2143
+ return INT2NUM(SSL_get_verify_result(ssl));
1840
2144
  }
1841
2145
 
1842
2146
  /*
@@ -1856,7 +2160,7 @@ ossl_ssl_get_client_ca_list(VALUE self)
1856
2160
  SSL *ssl;
1857
2161
  STACK_OF(X509_NAME) *ca;
1858
2162
 
1859
- ossl_ssl_data_get_struct(self, ssl);
2163
+ GetSSL(self, ssl);
1860
2164
 
1861
2165
  ca = SSL_get_client_CA_list(ssl);
1862
2166
  return ossl_x509name_sk2ary(ca);
@@ -1865,7 +2169,7 @@ ossl_ssl_get_client_ca_list(VALUE self)
1865
2169
  # ifdef HAVE_SSL_CTX_SET_NEXT_PROTO_SELECT_CB
1866
2170
  /*
1867
2171
  * call-seq:
1868
- * ssl.npn_protocol => String
2172
+ * ssl.npn_protocol => String | nil
1869
2173
  *
1870
2174
  * Returns the protocol string that was finally selected by the client
1871
2175
  * during the handshake.
@@ -1877,7 +2181,7 @@ ossl_ssl_npn_protocol(VALUE self)
1877
2181
  const unsigned char *out;
1878
2182
  unsigned int outlen;
1879
2183
 
1880
- ossl_ssl_data_get_struct(self, ssl);
2184
+ GetSSL(self, ssl);
1881
2185
 
1882
2186
  SSL_get0_next_proto_negotiated(ssl, &out, &outlen);
1883
2187
  if (!outlen)
@@ -1890,9 +2194,9 @@ ossl_ssl_npn_protocol(VALUE self)
1890
2194
  # ifdef HAVE_SSL_CTX_SET_ALPN_SELECT_CB
1891
2195
  /*
1892
2196
  * call-seq:
1893
- * ssl.alpn_protocol => String
2197
+ * ssl.alpn_protocol => String | nil
1894
2198
  *
1895
- * Returns the ALPN protocol string that was finally selected by the client
2199
+ * Returns the ALPN protocol string that was finally selected by the server
1896
2200
  * during the handshake.
1897
2201
  */
1898
2202
  static VALUE
@@ -1902,7 +2206,7 @@ ossl_ssl_alpn_protocol(VALUE self)
1902
2206
  const unsigned char *out;
1903
2207
  unsigned int outlen;
1904
2208
 
1905
- ossl_ssl_data_get_struct(self, ssl);
2209
+ GetSSL(self, ssl);
1906
2210
 
1907
2211
  SSL_get0_alpn_selected(ssl, &out, &outlen);
1908
2212
  if (!outlen)
@@ -1911,8 +2215,30 @@ ossl_ssl_alpn_protocol(VALUE self)
1911
2215
  return rb_str_new((const char *) out, outlen);
1912
2216
  }
1913
2217
  # endif
2218
+
2219
+ # ifdef HAVE_SSL_GET_SERVER_TMP_KEY
2220
+ /*
2221
+ * call-seq:
2222
+ * ssl.tmp_key => PKey or nil
2223
+ *
2224
+ * Returns the ephemeral key used in case of forward secrecy cipher.
2225
+ */
2226
+ static VALUE
2227
+ ossl_ssl_tmp_key(VALUE self)
2228
+ {
2229
+ SSL *ssl;
2230
+ EVP_PKEY *key;
2231
+
2232
+ GetSSL(self, ssl);
2233
+ if (!SSL_get_server_tmp_key(ssl, &key))
2234
+ return Qnil;
2235
+ return ossl_pkey_new(key);
2236
+ }
2237
+ # endif /* defined(HAVE_SSL_GET_SERVER_TMP_KEY) */
1914
2238
  #endif /* !defined(OPENSSL_NO_SOCK) */
1915
2239
 
2240
+ #undef rb_intern
2241
+ #define rb_intern(s) rb_intern_const(s)
1916
2242
  void
1917
2243
  Init_ossl_ssl(void)
1918
2244
  {
@@ -1920,10 +2246,13 @@ Init_ossl_ssl(void)
1920
2246
  VALUE ary;
1921
2247
 
1922
2248
  #if 0
1923
- mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
2249
+ mOSSL = rb_define_module("OpenSSL");
2250
+ eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
2251
+ rb_mWaitReadable = rb_define_module_under(rb_cIO, "WaitReadable");
2252
+ rb_mWaitWritable = rb_define_module_under(rb_cIO, "WaitWritable");
1924
2253
  #endif
1925
2254
 
1926
- ID_callback_state = rb_intern("@callback_state");
2255
+ ID_callback_state = rb_intern("callback_state");
1927
2256
 
1928
2257
  ossl_ssl_ex_vcb_idx = SSL_get_ex_new_index(0,(void *)"ossl_ssl_ex_vcb_idx",0,0,0);
1929
2258
  ossl_ssl_ex_store_p = SSL_get_ex_new_index(0,(void *)"ossl_ssl_ex_store_p",0,0,0);
@@ -1968,14 +2297,10 @@ Init_ossl_ssl(void)
1968
2297
  *
1969
2298
  * All attributes must be set before creating an SSLSocket as the
1970
2299
  * SSLContext will be frozen afterward.
1971
- *
1972
- * The following attributes are available but don't show up in rdoc:
1973
- * * ssl_version, cert, key, client_ca, ca_file, ca_path, timeout,
1974
- * * verify_mode, verify_depth client_cert_cb, tmp_dh_callback,
1975
- * * session_id_context, session_add_cb, session_new_cb, session_remove_cb
1976
2300
  */
1977
2301
  cSSLContext = rb_define_class_under(mSSL, "SSLContext", rb_cObject);
1978
2302
  rb_define_alloc_func(cSSLContext, ossl_sslctx_s_alloc);
2303
+ rb_undef_method(cSSLContext, "initialize_copy");
1979
2304
 
1980
2305
  /*
1981
2306
  * Context certificate
@@ -2005,7 +2330,7 @@ Init_ossl_ssl(void)
2005
2330
  rb_attr(cSSLContext, rb_intern("ca_path"), 1, 1, Qfalse);
2006
2331
 
2007
2332
  /*
2008
- * Maximum session lifetime.
2333
+ * Maximum session lifetime in seconds.
2009
2334
  */
2010
2335
  rb_attr(cSSLContext, rb_intern("timeout"), 1, 1, Qfalse);
2011
2336
 
@@ -2014,6 +2339,11 @@ Init_ossl_ssl(void)
2014
2339
  *
2015
2340
  * Valid modes are VERIFY_NONE, VERIFY_PEER, VERIFY_CLIENT_ONCE,
2016
2341
  * VERIFY_FAIL_IF_NO_PEER_CERT and defined on OpenSSL::SSL
2342
+ *
2343
+ * The default mode is VERIFY_NONE, which does not perform any verification
2344
+ * at all.
2345
+ *
2346
+ * See SSL_CTX_set_verify(3) for details.
2017
2347
  */
2018
2348
  rb_attr(cSSLContext, rb_intern("verify_mode"), 1, 1, Qfalse);
2019
2349
 
@@ -2031,12 +2361,21 @@ Init_ossl_ssl(void)
2031
2361
  * +store_context+ is an OpenSSL::X509::StoreContext containing the
2032
2362
  * context used for certificate verification.
2033
2363
  *
2034
- * If the callback returns false verification is stopped.
2364
+ * If the callback returns false, the chain verification is immediately
2365
+ * stopped and a bad_certificate alert is then sent.
2035
2366
  */
2036
2367
  rb_attr(cSSLContext, rb_intern("verify_callback"), 1, 1, Qfalse);
2037
2368
 
2038
2369
  /*
2039
- * An OpenSSL::X509::Store used for certificate verification
2370
+ * Whether to check the server certificate is valid for the hostname.
2371
+ *
2372
+ * In order to make this work, verify_mode must be set to VERIFY_PEER and
2373
+ * the server hostname must be given by OpenSSL::SSL::SSLSocket#hostname=.
2374
+ */
2375
+ rb_attr(cSSLContext, rb_intern("verify_hostname"), 1, 1, Qfalse);
2376
+
2377
+ /*
2378
+ * An OpenSSL::X509::Store used for certificate verification.
2040
2379
  */
2041
2380
  rb_attr(cSSLContext, rb_intern("cert_store"), 1, 1, Qfalse);
2042
2381
 
@@ -2056,6 +2395,7 @@ Init_ossl_ssl(void)
2056
2395
  */
2057
2396
  rb_attr(cSSLContext, rb_intern("client_cert_cb"), 1, 1, Qfalse);
2058
2397
 
2398
+ #if !defined(OPENSSL_NO_EC) && defined(HAVE_SSL_CTX_SET_TMP_ECDH_CALLBACK)
2059
2399
  /*
2060
2400
  * A callback invoked when ECDH parameters are required.
2061
2401
  *
@@ -2063,10 +2403,11 @@ Init_ossl_ssl(void)
2063
2403
  * flag indicating the use of an export cipher and the keylength
2064
2404
  * required.
2065
2405
  *
2066
- * The callback must return an OpenSSL::PKey::EC instance of the correct
2067
- * key length.
2406
+ * The callback is deprecated. This does not work with recent versions of
2407
+ * OpenSSL. Use OpenSSL::SSL::SSLContext#ecdh_curves= instead.
2068
2408
  */
2069
2409
  rb_attr(cSSLContext, rb_intern("tmp_ecdh_callback"), 1, 1, Qfalse);
2410
+ #endif
2070
2411
 
2071
2412
  /*
2072
2413
  * Sets the context in which a session can be reused. This allows
@@ -2096,6 +2437,10 @@ Init_ossl_ssl(void)
2096
2437
  * A callback invoked when a session is removed from the internal cache.
2097
2438
  *
2098
2439
  * The callback is invoked with an SSLContext and a Session.
2440
+ *
2441
+ * IMPORTANT NOTE: It is currently not possible to use this safely in a
2442
+ * multi-threaded application. The callback is called inside a global lock
2443
+ * and it can randomly cause deadlock on Ruby thread switching.
2099
2444
  */
2100
2445
  rb_attr(cSSLContext, rb_intern("session_remove_cb"), 1, 1, Qfalse);
2101
2446
 
@@ -2158,7 +2503,7 @@ Init_ossl_ssl(void)
2158
2503
  * === Example
2159
2504
  *
2160
2505
  * ctx.npn_select_cb = lambda do |protocols|
2161
- * #inspect the protocols and select one
2506
+ * # inspect the protocols and select one
2162
2507
  * protocols.first
2163
2508
  * end
2164
2509
  */
@@ -2168,10 +2513,10 @@ Init_ossl_ssl(void)
2168
2513
  #ifdef HAVE_SSL_CTX_SET_ALPN_SELECT_CB
2169
2514
  /*
2170
2515
  * An Enumerable of Strings. Each String represents a protocol to be
2171
- * advertised as the list of supported protocols for Application-Layer Protocol
2172
- * Negotiation. Supported in OpenSSL 1.0.1 and higher. Has no effect
2173
- * on the client side. If not set explicitly, the NPN extension will
2174
- * not be sent by the server in the handshake.
2516
+ * advertised as the list of supported protocols for Application-Layer
2517
+ * Protocol Negotiation. Supported in OpenSSL 1.0.2 and higher. Has no
2518
+ * effect on the server side. If not set explicitly, the ALPN extension will
2519
+ * not be included in the handshake.
2175
2520
  *
2176
2521
  * === Example
2177
2522
  *
@@ -2181,16 +2526,16 @@ Init_ossl_ssl(void)
2181
2526
  /*
2182
2527
  * A callback invoked on the server side when the server needs to select
2183
2528
  * a protocol from the list sent by the client. Supported in OpenSSL 1.0.2
2184
- * and higher. The server MUST select a protocol of those advertised by
2529
+ * and higher. The callback must return a protocol of those advertised by
2185
2530
  * the client. If none is acceptable, raising an error in the callback
2186
2531
  * will cause the handshake to fail. Not setting this callback explicitly
2187
- * means not supporting the ALPN extension on the client - any protocols
2188
- * advertised by the server will be ignored.
2532
+ * means not supporting the ALPN extension on the server - any protocols
2533
+ * advertised by the client will be ignored.
2189
2534
  *
2190
2535
  * === Example
2191
2536
  *
2192
2537
  * ctx.alpn_select_cb = lambda do |protocols|
2193
- * #inspect the protocols and select one
2538
+ * # inspect the protocols and select one
2194
2539
  * protocols.first
2195
2540
  * end
2196
2541
  */
@@ -2202,28 +2547,32 @@ Init_ossl_ssl(void)
2202
2547
  rb_define_method(cSSLContext, "ssl_version=", ossl_sslctx_set_ssl_version, 1);
2203
2548
  rb_define_method(cSSLContext, "ciphers", ossl_sslctx_get_ciphers, 0);
2204
2549
  rb_define_method(cSSLContext, "ciphers=", ossl_sslctx_set_ciphers, 1);
2550
+ rb_define_method(cSSLContext, "ecdh_curves=", ossl_sslctx_set_ecdh_curves, 1);
2551
+ rb_define_method(cSSLContext, "security_level", ossl_sslctx_get_security_level, 0);
2552
+ rb_define_method(cSSLContext, "security_level=", ossl_sslctx_set_security_level, 1);
2205
2553
 
2206
2554
  rb_define_method(cSSLContext, "setup", ossl_sslctx_setup, 0);
2555
+ rb_define_alias(cSSLContext, "freeze", "setup");
2207
2556
 
2208
2557
  /*
2209
2558
  * No session caching for client or server
2210
2559
  */
2211
- rb_define_const(cSSLContext, "SESSION_CACHE_OFF", LONG2FIX(SSL_SESS_CACHE_OFF));
2560
+ rb_define_const(cSSLContext, "SESSION_CACHE_OFF", LONG2NUM(SSL_SESS_CACHE_OFF));
2212
2561
 
2213
2562
  /*
2214
2563
  * Client sessions are added to the session cache
2215
2564
  */
2216
- rb_define_const(cSSLContext, "SESSION_CACHE_CLIENT", LONG2FIX(SSL_SESS_CACHE_CLIENT)); /* doesn't actually do anything in 0.9.8e */
2565
+ rb_define_const(cSSLContext, "SESSION_CACHE_CLIENT", LONG2NUM(SSL_SESS_CACHE_CLIENT)); /* doesn't actually do anything in 0.9.8e */
2217
2566
 
2218
2567
  /*
2219
2568
  * Server sessions are added to the session cache
2220
2569
  */
2221
- rb_define_const(cSSLContext, "SESSION_CACHE_SERVER", LONG2FIX(SSL_SESS_CACHE_SERVER));
2570
+ rb_define_const(cSSLContext, "SESSION_CACHE_SERVER", LONG2NUM(SSL_SESS_CACHE_SERVER));
2222
2571
 
2223
2572
  /*
2224
2573
  * Both client and server sessions are added to the session cache
2225
2574
  */
2226
- rb_define_const(cSSLContext, "SESSION_CACHE_BOTH", LONG2FIX(SSL_SESS_CACHE_BOTH)); /* no different than CACHE_SERVER in 0.9.8e */
2575
+ rb_define_const(cSSLContext, "SESSION_CACHE_BOTH", LONG2NUM(SSL_SESS_CACHE_BOTH)); /* no different than CACHE_SERVER in 0.9.8e */
2227
2576
 
2228
2577
  /*
2229
2578
  * Normally the session cache is checked for expired sessions every 255
@@ -2231,7 +2580,7 @@ Init_ossl_ssl(void)
2231
2580
  * the automatic flushing may be disabled and #flush_sessions can be
2232
2581
  * called explicitly.
2233
2582
  */
2234
- rb_define_const(cSSLContext, "SESSION_CACHE_NO_AUTO_CLEAR", LONG2FIX(SSL_SESS_CACHE_NO_AUTO_CLEAR));
2583
+ rb_define_const(cSSLContext, "SESSION_CACHE_NO_AUTO_CLEAR", LONG2NUM(SSL_SESS_CACHE_NO_AUTO_CLEAR));
2235
2584
 
2236
2585
  /*
2237
2586
  * Always perform external lookups of sessions even if they are in the
@@ -2239,18 +2588,18 @@ Init_ossl_ssl(void)
2239
2588
  *
2240
2589
  * This flag has no effect on clients
2241
2590
  */
2242
- rb_define_const(cSSLContext, "SESSION_CACHE_NO_INTERNAL_LOOKUP", LONG2FIX(SSL_SESS_CACHE_NO_INTERNAL_LOOKUP));
2591
+ rb_define_const(cSSLContext, "SESSION_CACHE_NO_INTERNAL_LOOKUP", LONG2NUM(SSL_SESS_CACHE_NO_INTERNAL_LOOKUP));
2243
2592
 
2244
2593
  /*
2245
2594
  * Never automatically store sessions in the internal store.
2246
2595
  */
2247
- rb_define_const(cSSLContext, "SESSION_CACHE_NO_INTERNAL_STORE", LONG2FIX(SSL_SESS_CACHE_NO_INTERNAL_STORE));
2596
+ rb_define_const(cSSLContext, "SESSION_CACHE_NO_INTERNAL_STORE", LONG2NUM(SSL_SESS_CACHE_NO_INTERNAL_STORE));
2248
2597
 
2249
2598
  /*
2250
2599
  * Enables both SESSION_CACHE_NO_INTERNAL_LOOKUP and
2251
2600
  * SESSION_CACHE_NO_INTERNAL_STORE.
2252
2601
  */
2253
- rb_define_const(cSSLContext, "SESSION_CACHE_NO_INTERNAL", LONG2FIX(SSL_SESS_CACHE_NO_INTERNAL));
2602
+ rb_define_const(cSSLContext, "SESSION_CACHE_NO_INTERNAL", LONG2NUM(SSL_SESS_CACHE_NO_INTERNAL));
2254
2603
 
2255
2604
  rb_define_method(cSSLContext, "session_add", ossl_sslctx_session_add, 1);
2256
2605
  rb_define_method(cSSLContext, "session_remove", ossl_sslctx_session_remove, 1);
@@ -2273,17 +2622,16 @@ Init_ossl_ssl(void)
2273
2622
 
2274
2623
  /*
2275
2624
  * Document-class: OpenSSL::SSL::SSLSocket
2276
- *
2277
- * The following attributes are available but don't show up in rdoc.
2278
- * * io, context, sync_close
2279
- *
2280
2625
  */
2281
2626
  cSSLSocket = rb_define_class_under(mSSL, "SSLSocket", rb_cObject);
2282
2627
  #ifdef OPENSSL_NO_SOCK
2283
2628
  rb_define_const(mSSLExtConfig, "OPENSSL_NO_SOCK", Qtrue);
2629
+ rb_define_method(cSSLSocket, "initialize", rb_f_notimplement, -1);
2284
2630
  #else
2285
2631
  rb_define_const(mSSLExtConfig, "OPENSSL_NO_SOCK", Qfalse);
2286
2632
  rb_define_alloc_func(cSSLSocket, ossl_ssl_s_alloc);
2633
+ rb_define_method(cSSLSocket, "initialize", ossl_ssl_initialize, -1);
2634
+ rb_undef_method(cSSLSocket, "initialize_copy");
2287
2635
  rb_define_method(cSSLSocket, "connect", ossl_ssl_connect, 0);
2288
2636
  rb_define_method(cSSLSocket, "connect_nonblock", ossl_ssl_connect_nonblock, -1);
2289
2637
  rb_define_method(cSSLSocket, "accept", ossl_ssl_accept, 0);
@@ -2305,6 +2653,13 @@ Init_ossl_ssl(void)
2305
2653
  rb_define_method(cSSLSocket, "session=", ossl_ssl_set_session, 1);
2306
2654
  rb_define_method(cSSLSocket, "verify_result", ossl_ssl_get_verify_result, 0);
2307
2655
  rb_define_method(cSSLSocket, "client_ca", ossl_ssl_get_client_ca_list, 0);
2656
+ #ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME
2657
+ /* #hostname is defined in lib/openssl/ssl.rb */
2658
+ rb_define_method(cSSLSocket, "hostname=", ossl_ssl_set_hostname, 1);
2659
+ #endif
2660
+ # ifdef HAVE_SSL_GET_SERVER_TMP_KEY
2661
+ rb_define_method(cSSLSocket, "tmp_key", ossl_ssl_tmp_key, 0);
2662
+ # endif
2308
2663
  # ifdef HAVE_SSL_CTX_SET_ALPN_SELECT_CB
2309
2664
  rb_define_method(cSSLSocket, "alpn_protocol", ossl_ssl_alpn_protocol, 0);
2310
2665
  # endif
@@ -2328,25 +2683,17 @@ Init_ossl_ssl(void)
2328
2683
  ossl_ssl_def_const(OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG);
2329
2684
  ossl_ssl_def_const(OP_SSLREF2_REUSE_CERT_TYPE_BUG);
2330
2685
  ossl_ssl_def_const(OP_MICROSOFT_BIG_SSLV3_BUFFER);
2331
- #if defined(SSL_OP_MSIE_SSLV2_RSA_PADDING)
2332
2686
  ossl_ssl_def_const(OP_MSIE_SSLV2_RSA_PADDING);
2333
- #endif
2334
2687
  ossl_ssl_def_const(OP_SSLEAY_080_CLIENT_DH_BUG);
2335
2688
  ossl_ssl_def_const(OP_TLS_D5_BUG);
2336
2689
  ossl_ssl_def_const(OP_TLS_BLOCK_PADDING_BUG);
2337
2690
  ossl_ssl_def_const(OP_DONT_INSERT_EMPTY_FRAGMENTS);
2338
2691
  ossl_ssl_def_const(OP_ALL);
2339
- #if defined(SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION)
2340
2692
  ossl_ssl_def_const(OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
2341
- #endif
2342
- #if defined(SSL_OP_SINGLE_ECDH_USE)
2343
2693
  ossl_ssl_def_const(OP_SINGLE_ECDH_USE);
2344
- #endif
2345
2694
  ossl_ssl_def_const(OP_SINGLE_DH_USE);
2346
2695
  ossl_ssl_def_const(OP_EPHEMERAL_RSA);
2347
- #if defined(SSL_OP_CIPHER_SERVER_PREFERENCE)
2348
2696
  ossl_ssl_def_const(OP_CIPHER_SERVER_PREFERENCE);
2349
- #endif
2350
2697
  ossl_ssl_def_const(OP_TLS_ROLLBACK_BUG);
2351
2698
  ossl_ssl_def_const(OP_NO_SSLv2);
2352
2699
  ossl_ssl_def_const(OP_NO_SSLv3);
@@ -2368,8 +2715,43 @@ Init_ossl_ssl(void)
2368
2715
  ossl_ssl_def_const(OP_NETSCAPE_CA_DN_BUG);
2369
2716
  ossl_ssl_def_const(OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG);
2370
2717
 
2371
- #undef rb_intern
2372
2718
  sym_exception = ID2SYM(rb_intern("exception"));
2373
2719
  sym_wait_readable = ID2SYM(rb_intern("wait_readable"));
2374
2720
  sym_wait_writable = ID2SYM(rb_intern("wait_writable"));
2721
+
2722
+ id_tmp_dh_callback = rb_intern("tmp_dh_callback");
2723
+ id_tmp_ecdh_callback = rb_intern("tmp_ecdh_callback");
2724
+ id_npn_protocols_encoded = rb_intern("npn_protocols_encoded");
2725
+
2726
+ #define DefIVarID(name) do \
2727
+ id_i_##name = rb_intern("@"#name); while (0)
2728
+
2729
+ DefIVarID(cert_store);
2730
+ DefIVarID(ca_file);
2731
+ DefIVarID(ca_path);
2732
+ DefIVarID(verify_mode);
2733
+ DefIVarID(verify_depth);
2734
+ DefIVarID(verify_callback);
2735
+ DefIVarID(client_ca);
2736
+ DefIVarID(renegotiation_cb);
2737
+ DefIVarID(cert);
2738
+ DefIVarID(key);
2739
+ DefIVarID(extra_chain_cert);
2740
+ DefIVarID(client_cert_cb);
2741
+ DefIVarID(tmp_ecdh_callback);
2742
+ DefIVarID(timeout);
2743
+ DefIVarID(session_id_context);
2744
+ DefIVarID(session_get_cb);
2745
+ DefIVarID(session_new_cb);
2746
+ DefIVarID(session_remove_cb);
2747
+ DefIVarID(npn_select_cb);
2748
+ DefIVarID(npn_protocols);
2749
+ DefIVarID(alpn_protocols);
2750
+ DefIVarID(alpn_select_cb);
2751
+ DefIVarID(servername_cb);
2752
+ DefIVarID(verify_hostname);
2753
+
2754
+ DefIVarID(io);
2755
+ DefIVarID(context);
2756
+ DefIVarID(hostname);
2375
2757
  }