openssl 2.0.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of openssl might be problematic. Click here for more details.

Files changed (71) hide show
  1. checksums.yaml +7 -0
  2. data/BSDL +22 -0
  3. data/CONTRIBUTING.md +130 -0
  4. data/History.md +118 -0
  5. data/LICENSE.txt +56 -0
  6. data/README.md +70 -0
  7. data/ext/openssl/deprecation.rb +26 -0
  8. data/ext/openssl/extconf.rb +158 -0
  9. data/ext/openssl/openssl_missing.c +173 -0
  10. data/ext/openssl/openssl_missing.h +244 -0
  11. data/ext/openssl/ossl.c +1201 -0
  12. data/ext/openssl/ossl.h +222 -0
  13. data/ext/openssl/ossl_asn1.c +1992 -0
  14. data/ext/openssl/ossl_asn1.h +66 -0
  15. data/ext/openssl/ossl_bio.c +87 -0
  16. data/ext/openssl/ossl_bio.h +19 -0
  17. data/ext/openssl/ossl_bn.c +1153 -0
  18. data/ext/openssl/ossl_bn.h +23 -0
  19. data/ext/openssl/ossl_cipher.c +1085 -0
  20. data/ext/openssl/ossl_cipher.h +20 -0
  21. data/ext/openssl/ossl_config.c +89 -0
  22. data/ext/openssl/ossl_config.h +19 -0
  23. data/ext/openssl/ossl_digest.c +453 -0
  24. data/ext/openssl/ossl_digest.h +20 -0
  25. data/ext/openssl/ossl_engine.c +580 -0
  26. data/ext/openssl/ossl_engine.h +19 -0
  27. data/ext/openssl/ossl_hmac.c +398 -0
  28. data/ext/openssl/ossl_hmac.h +18 -0
  29. data/ext/openssl/ossl_ns_spki.c +406 -0
  30. data/ext/openssl/ossl_ns_spki.h +19 -0
  31. data/ext/openssl/ossl_ocsp.c +2013 -0
  32. data/ext/openssl/ossl_ocsp.h +23 -0
  33. data/ext/openssl/ossl_pkcs12.c +259 -0
  34. data/ext/openssl/ossl_pkcs12.h +13 -0
  35. data/ext/openssl/ossl_pkcs5.c +180 -0
  36. data/ext/openssl/ossl_pkcs5.h +6 -0
  37. data/ext/openssl/ossl_pkcs7.c +1125 -0
  38. data/ext/openssl/ossl_pkcs7.h +20 -0
  39. data/ext/openssl/ossl_pkey.c +435 -0
  40. data/ext/openssl/ossl_pkey.h +245 -0
  41. data/ext/openssl/ossl_pkey_dh.c +650 -0
  42. data/ext/openssl/ossl_pkey_dsa.c +672 -0
  43. data/ext/openssl/ossl_pkey_ec.c +1899 -0
  44. data/ext/openssl/ossl_pkey_rsa.c +768 -0
  45. data/ext/openssl/ossl_rand.c +238 -0
  46. data/ext/openssl/ossl_rand.h +18 -0
  47. data/ext/openssl/ossl_ssl.c +2679 -0
  48. data/ext/openssl/ossl_ssl.h +41 -0
  49. data/ext/openssl/ossl_ssl_session.c +352 -0
  50. data/ext/openssl/ossl_version.h +15 -0
  51. data/ext/openssl/ossl_x509.c +186 -0
  52. data/ext/openssl/ossl_x509.h +119 -0
  53. data/ext/openssl/ossl_x509attr.c +328 -0
  54. data/ext/openssl/ossl_x509cert.c +860 -0
  55. data/ext/openssl/ossl_x509crl.c +565 -0
  56. data/ext/openssl/ossl_x509ext.c +480 -0
  57. data/ext/openssl/ossl_x509name.c +547 -0
  58. data/ext/openssl/ossl_x509req.c +492 -0
  59. data/ext/openssl/ossl_x509revoked.c +279 -0
  60. data/ext/openssl/ossl_x509store.c +846 -0
  61. data/ext/openssl/ruby_missing.h +32 -0
  62. data/lib/openssl.rb +21 -0
  63. data/lib/openssl/bn.rb +39 -0
  64. data/lib/openssl/buffering.rb +451 -0
  65. data/lib/openssl/cipher.rb +67 -0
  66. data/lib/openssl/config.rb +473 -0
  67. data/lib/openssl/digest.rb +78 -0
  68. data/lib/openssl/pkey.rb +44 -0
  69. data/lib/openssl/ssl.rb +416 -0
  70. data/lib/openssl/x509.rb +176 -0
  71. metadata +178 -0
@@ -0,0 +1,238 @@
1
+ /*
2
+ * 'OpenSSL for Ruby' project
3
+ * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
4
+ *
5
+ * All rights reserved.
6
+ *
7
+ * This program is licensed under the same licence as Ruby.
8
+ * (See the file 'LICENCE'.)
9
+ */
10
+ #include "ossl.h"
11
+
12
+ VALUE mRandom;
13
+ VALUE eRandomError;
14
+
15
+ /*
16
+ * call-seq:
17
+ * seed(str) -> str
18
+ *
19
+ * ::seed is equivalent to ::add where +entropy+ is length of +str+.
20
+ */
21
+ static VALUE
22
+ ossl_rand_seed(VALUE self, VALUE str)
23
+ {
24
+ StringValue(str);
25
+ RAND_seed(RSTRING_PTR(str), RSTRING_LENINT(str));
26
+
27
+ return str;
28
+ }
29
+
30
+ /*
31
+ * call-seq:
32
+ * add(str, entropy) -> self
33
+ *
34
+ * Mixes the bytes from +str+ into the Pseudo Random Number Generator(PRNG)
35
+ * state.
36
+ *
37
+ * Thus, if the data from +str+ are unpredictable to an adversary, this
38
+ * increases the uncertainty about the state and makes the PRNG output less
39
+ * predictable.
40
+ *
41
+ * The +entropy+ argument is (the lower bound of) an estimate of how much
42
+ * randomness is contained in +str+, measured in bytes.
43
+ *
44
+ * === Example
45
+ *
46
+ * pid = $$
47
+ * now = Time.now
48
+ * ary = [now.to_i, now.nsec, 1000, pid]
49
+ * OpenSSL::Random.add(ary.join, 0.0)
50
+ * OpenSSL::Random.seed(ary.join)
51
+ */
52
+ static VALUE
53
+ ossl_rand_add(VALUE self, VALUE str, VALUE entropy)
54
+ {
55
+ StringValue(str);
56
+ RAND_add(RSTRING_PTR(str), RSTRING_LENINT(str), NUM2DBL(entropy));
57
+
58
+ return self;
59
+ }
60
+
61
+ /*
62
+ * call-seq:
63
+ * load_random_file(filename) -> true
64
+ *
65
+ * Reads bytes from +filename+ and adds them to the PRNG.
66
+ */
67
+ static VALUE
68
+ ossl_rand_load_file(VALUE self, VALUE filename)
69
+ {
70
+ rb_check_safe_obj(filename);
71
+
72
+ if(!RAND_load_file(StringValueCStr(filename), -1)) {
73
+ ossl_raise(eRandomError, NULL);
74
+ }
75
+ return Qtrue;
76
+ }
77
+
78
+ /*
79
+ * call-seq:
80
+ * write_random_file(filename) -> true
81
+ *
82
+ * Writes a number of random generated bytes (currently 1024) to +filename+
83
+ * which can be used to initialize the PRNG by calling ::load_random_file in a
84
+ * later session.
85
+ */
86
+ static VALUE
87
+ ossl_rand_write_file(VALUE self, VALUE filename)
88
+ {
89
+ rb_check_safe_obj(filename);
90
+
91
+ if (RAND_write_file(StringValueCStr(filename)) == -1) {
92
+ ossl_raise(eRandomError, NULL);
93
+ }
94
+ return Qtrue;
95
+ }
96
+
97
+ /*
98
+ * call-seq:
99
+ * random_bytes(length) -> string
100
+ *
101
+ * Generates +string+ with +length+ number of cryptographically strong
102
+ * pseudo-random bytes.
103
+ *
104
+ * === Example
105
+ *
106
+ * OpenSSL::Random.random_bytes(12)
107
+ * #=> "..."
108
+ */
109
+ static VALUE
110
+ ossl_rand_bytes(VALUE self, VALUE len)
111
+ {
112
+ VALUE str;
113
+ int n = NUM2INT(len);
114
+ int ret;
115
+
116
+ str = rb_str_new(0, n);
117
+ ret = RAND_bytes((unsigned char *)RSTRING_PTR(str), n);
118
+ if (ret == 0) {
119
+ ossl_raise(eRandomError, "RAND_bytes");
120
+ } else if (ret == -1) {
121
+ ossl_raise(eRandomError, "RAND_bytes is not supported");
122
+ }
123
+
124
+ return str;
125
+ }
126
+
127
+ #if defined(HAVE_RAND_PSEUDO_BYTES)
128
+ /*
129
+ * call-seq:
130
+ * pseudo_bytes(length) -> string
131
+ *
132
+ * Generates +string+ with +length+ number of pseudo-random bytes.
133
+ *
134
+ * Pseudo-random byte sequences generated by ::pseudo_bytes will be unique if
135
+ * they are of sufficient length, but are not necessarily unpredictable.
136
+ *
137
+ * === Example
138
+ *
139
+ * OpenSSL::Random.pseudo_bytes(12)
140
+ * #=> "..."
141
+ */
142
+ static VALUE
143
+ ossl_rand_pseudo_bytes(VALUE self, VALUE len)
144
+ {
145
+ VALUE str;
146
+ int n = NUM2INT(len);
147
+
148
+ str = rb_str_new(0, n);
149
+ if (RAND_pseudo_bytes((unsigned char *)RSTRING_PTR(str), n) < 1) {
150
+ ossl_raise(eRandomError, NULL);
151
+ }
152
+
153
+ return str;
154
+ }
155
+ #endif
156
+
157
+ #ifdef HAVE_RAND_EGD
158
+ /*
159
+ * call-seq:
160
+ * egd(filename) -> true
161
+ *
162
+ * Same as ::egd_bytes but queries 255 bytes by default.
163
+ */
164
+ static VALUE
165
+ ossl_rand_egd(VALUE self, VALUE filename)
166
+ {
167
+ rb_check_safe_obj(filename);
168
+
169
+ if (RAND_egd(StringValueCStr(filename)) == -1) {
170
+ ossl_raise(eRandomError, NULL);
171
+ }
172
+ return Qtrue;
173
+ }
174
+
175
+ /*
176
+ * call-seq:
177
+ * egd_bytes(filename, length) -> true
178
+ *
179
+ * Queries the entropy gathering daemon EGD on socket path given by +filename+.
180
+ *
181
+ * Fetches +length+ number of bytes and uses ::add to seed the OpenSSL built-in
182
+ * PRNG.
183
+ */
184
+ static VALUE
185
+ ossl_rand_egd_bytes(VALUE self, VALUE filename, VALUE len)
186
+ {
187
+ int n = NUM2INT(len);
188
+
189
+ rb_check_safe_obj(filename);
190
+
191
+ if (RAND_egd_bytes(StringValueCStr(filename), n) == -1) {
192
+ ossl_raise(eRandomError, NULL);
193
+ }
194
+ return Qtrue;
195
+ }
196
+ #endif /* HAVE_RAND_EGD */
197
+
198
+ /*
199
+ * call-seq:
200
+ * status? => true | false
201
+ *
202
+ * Return true if the PRNG has been seeded with enough data, false otherwise.
203
+ */
204
+ static VALUE
205
+ ossl_rand_status(VALUE self)
206
+ {
207
+ return RAND_status() ? Qtrue : Qfalse;
208
+ }
209
+
210
+ /*
211
+ * INIT
212
+ */
213
+ void
214
+ Init_ossl_rand(void)
215
+ {
216
+ #if 0
217
+ mOSSL = rb_define_module("OpenSSL");
218
+ eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
219
+ #endif
220
+
221
+ mRandom = rb_define_module_under(mOSSL, "Random");
222
+
223
+ eRandomError = rb_define_class_under(mRandom, "RandomError", eOSSLError);
224
+
225
+ rb_define_module_function(mRandom, "seed", ossl_rand_seed, 1);
226
+ rb_define_module_function(mRandom, "random_add", ossl_rand_add, 2);
227
+ rb_define_module_function(mRandom, "load_random_file", ossl_rand_load_file, 1);
228
+ rb_define_module_function(mRandom, "write_random_file", ossl_rand_write_file, 1);
229
+ rb_define_module_function(mRandom, "random_bytes", ossl_rand_bytes, 1);
230
+ #if defined(HAVE_RAND_PSEUDO_BYTES)
231
+ rb_define_module_function(mRandom, "pseudo_bytes", ossl_rand_pseudo_bytes, 1);
232
+ #endif
233
+ #ifdef HAVE_RAND_EGD
234
+ rb_define_module_function(mRandom, "egd", ossl_rand_egd, 1);
235
+ rb_define_module_function(mRandom, "egd_bytes", ossl_rand_egd_bytes, 2);
236
+ #endif /* HAVE_RAND_EGD */
237
+ rb_define_module_function(mRandom, "status?", ossl_rand_status, 0);
238
+ }
@@ -0,0 +1,18 @@
1
+ /*
2
+ * 'OpenSSL for Ruby' project
3
+ * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
4
+ * All rights reserved.
5
+ */
6
+ /*
7
+ * This program is licensed under the same licence as Ruby.
8
+ * (See the file 'LICENCE'.)
9
+ */
10
+ #if !defined(_OSSL_RAND_H_)
11
+ #define _OSSL_RAND_H_
12
+
13
+ extern VALUE mRandom;
14
+ extern VALUE eRandomError;
15
+
16
+ void Init_ossl_rand(void);
17
+
18
+ #endif /* _OSSL_RAND_H_ */
@@ -0,0 +1,2679 @@
1
+ /*
2
+ * 'OpenSSL for Ruby' project
3
+ * Copyright (C) 2000-2002 GOTOU Yuuzou <gotoyuzo@notwork.org>
4
+ * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
5
+ * Copyright (C) 2001-2007 Technorama Ltd. <oss-ruby@technorama.net>
6
+ * All rights reserved.
7
+ */
8
+ /*
9
+ * This program is licensed under the same licence as Ruby.
10
+ * (See the file 'LICENCE'.)
11
+ */
12
+ #include "ossl.h"
13
+
14
+ #if defined(HAVE_UNISTD_H)
15
+ # include <unistd.h> /* for read(), and write() */
16
+ #endif
17
+
18
+ #define numberof(ary) (int)(sizeof(ary)/sizeof((ary)[0]))
19
+
20
+ #ifdef _WIN32
21
+ # define TO_SOCKET(s) _get_osfhandle(s)
22
+ #else
23
+ # define TO_SOCKET(s) (s)
24
+ #endif
25
+
26
+ #define GetSSLCTX(obj, ctx) do { \
27
+ TypedData_Get_Struct((obj), SSL_CTX, &ossl_sslctx_type, (ctx)); \
28
+ } while (0)
29
+
30
+ VALUE mSSL;
31
+ static VALUE mSSLExtConfig;
32
+ static VALUE eSSLError;
33
+ VALUE cSSLContext;
34
+ VALUE cSSLSocket;
35
+
36
+ static VALUE eSSLErrorWaitReadable;
37
+ static VALUE eSSLErrorWaitWritable;
38
+
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
+ #define ossl_sslctx_get_verify_hostname(o) rb_iv_get((o),"@verify_hostname")
68
+
69
+ #define ossl_ssl_get_io(o) rb_iv_get((o),"@io")
70
+ #define ossl_ssl_get_ctx(o) rb_iv_get((o),"@context")
71
+
72
+ #define ossl_ssl_set_io(o,v) rb_iv_set((o),"@io",(v))
73
+ #define ossl_ssl_set_ctx(o,v) rb_iv_set((o),"@context",(v))
74
+ #define ossl_ssl_set_sync_close(o,v) rb_iv_set((o),"@sync_close",(v))
75
+ #define ossl_ssl_set_hostname_v(o,v) rb_iv_set((o),"@hostname",(v))
76
+ #define ossl_ssl_set_tmp_dh(o,v) rb_iv_set((o),"@tmp_dh",(v))
77
+ #define ossl_ssl_set_tmp_ecdh(o,v) rb_iv_set((o),"@tmp_ecdh",(v))
78
+
79
+ static ID ID_callback_state;
80
+
81
+ static VALUE sym_exception, sym_wait_readable, sym_wait_writable;
82
+
83
+ /*
84
+ * SSLContext class
85
+ */
86
+ static const struct {
87
+ const char *name;
88
+ SSL_METHOD *(*func)(void); /* FIXME: constify when dropping 0.9.8 */
89
+ int version;
90
+ } ossl_ssl_method_tab[] = {
91
+ #if defined(HAVE_SSL_CTX_SET_MIN_PROTO_VERSION)
92
+ #define OSSL_SSL_METHOD_ENTRY(name, version) \
93
+ { #name, (SSL_METHOD *(*)(void))TLS_method, version }, \
94
+ { #name"_server", (SSL_METHOD *(*)(void))TLS_server_method, version }, \
95
+ { #name"_client", (SSL_METHOD *(*)(void))TLS_client_method, version }
96
+ #else
97
+ #define OSSL_SSL_METHOD_ENTRY(name, version) \
98
+ { #name, (SSL_METHOD *(*)(void))name##_method, version }, \
99
+ { #name"_server", (SSL_METHOD *(*)(void))name##_server_method, version }, \
100
+ { #name"_client", (SSL_METHOD *(*)(void))name##_client_method, version }
101
+ #endif
102
+ #if defined(HAVE_SSLV2_METHOD)
103
+ OSSL_SSL_METHOD_ENTRY(SSLv2, SSL2_VERSION),
104
+ #endif
105
+ #if defined(HAVE_SSLV3_METHOD)
106
+ OSSL_SSL_METHOD_ENTRY(SSLv3, SSL3_VERSION),
107
+ #endif
108
+ OSSL_SSL_METHOD_ENTRY(TLSv1, TLS1_VERSION),
109
+ #if defined(HAVE_TLSV1_1_METHOD)
110
+ OSSL_SSL_METHOD_ENTRY(TLSv1_1, TLS1_1_VERSION),
111
+ #endif
112
+ #if defined(HAVE_TLSV1_2_METHOD)
113
+ OSSL_SSL_METHOD_ENTRY(TLSv1_2, TLS1_2_VERSION),
114
+ #endif
115
+ OSSL_SSL_METHOD_ENTRY(SSLv23, 0),
116
+ #undef OSSL_SSL_METHOD_ENTRY
117
+ };
118
+
119
+ static int ossl_ssl_ex_vcb_idx;
120
+ static int ossl_ssl_ex_store_p;
121
+ static int ossl_ssl_ex_ptr_idx;
122
+
123
+ static void
124
+ ossl_sslctx_free(void *ptr)
125
+ {
126
+ SSL_CTX *ctx = ptr;
127
+ #if !defined(HAVE_X509_STORE_UP_REF)
128
+ if(ctx && SSL_CTX_get_ex_data(ctx, ossl_ssl_ex_store_p)== (void*)1)
129
+ ctx->cert_store = NULL;
130
+ #endif
131
+ SSL_CTX_free(ctx);
132
+ }
133
+
134
+ static const rb_data_type_t ossl_sslctx_type = {
135
+ "OpenSSL/SSL/CTX",
136
+ {
137
+ 0, ossl_sslctx_free,
138
+ },
139
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
140
+ };
141
+
142
+ static VALUE
143
+ ossl_sslctx_s_alloc(VALUE klass)
144
+ {
145
+ SSL_CTX *ctx;
146
+ long mode = SSL_MODE_ENABLE_PARTIAL_WRITE |
147
+ SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER;
148
+ VALUE obj;
149
+
150
+ #ifdef SSL_MODE_RELEASE_BUFFERS
151
+ mode |= SSL_MODE_RELEASE_BUFFERS;
152
+ #endif
153
+
154
+ obj = TypedData_Wrap_Struct(klass, &ossl_sslctx_type, 0);
155
+ ctx = SSL_CTX_new(SSLv23_method());
156
+ if (!ctx) {
157
+ ossl_raise(eSSLError, "SSL_CTX_new");
158
+ }
159
+ SSL_CTX_set_mode(ctx, mode);
160
+ RTYPEDDATA_DATA(obj) = ctx;
161
+ SSL_CTX_set_ex_data(ctx, ossl_ssl_ex_ptr_idx, (void*)obj);
162
+
163
+ #if !defined(OPENSSL_NO_EC) && defined(HAVE_SSL_CTX_SET_ECDH_AUTO)
164
+ /* We use SSL_CTX_set1_curves_list() to specify the curve used in ECDH. It
165
+ * allows to specify multiple curve names and OpenSSL will select
166
+ * automatically from them. In OpenSSL 1.0.2, the automatic selection has to
167
+ * be enabled explicitly. But OpenSSL 1.1.0 removed the knob and it is
168
+ * always enabled. To uniform the behavior, we enable the automatic
169
+ * selection also in 1.0.2. Users can still disable ECDH by removing ECDH
170
+ * cipher suites by SSLContext#ciphers=. */
171
+ if (!SSL_CTX_set_ecdh_auto(ctx, 1))
172
+ ossl_raise(eSSLError, "SSL_CTX_set_ecdh_auto");
173
+ #endif
174
+
175
+ return obj;
176
+ }
177
+
178
+ /*
179
+ * call-seq:
180
+ * ctx.ssl_version = :TLSv1
181
+ * ctx.ssl_version = "SSLv23_client"
182
+ *
183
+ * Sets the SSL/TLS protocol version for the context. This forces connections to
184
+ * use only the specified protocol version.
185
+ *
186
+ * You can get a list of valid versions with OpenSSL::SSL::SSLContext::METHODS
187
+ */
188
+ static VALUE
189
+ ossl_sslctx_set_ssl_version(VALUE self, VALUE ssl_method)
190
+ {
191
+ SSL_CTX *ctx;
192
+ const char *s;
193
+ VALUE m = ssl_method;
194
+ int i;
195
+
196
+ GetSSLCTX(self, ctx);
197
+ if (RB_TYPE_P(ssl_method, T_SYMBOL))
198
+ m = rb_sym2str(ssl_method);
199
+ s = StringValueCStr(m);
200
+ for (i = 0; i < numberof(ossl_ssl_method_tab); i++) {
201
+ if (strcmp(ossl_ssl_method_tab[i].name, s) == 0) {
202
+ #if defined(HAVE_SSL_CTX_SET_MIN_PROTO_VERSION)
203
+ int version = ossl_ssl_method_tab[i].version;
204
+ #endif
205
+ SSL_METHOD *method = ossl_ssl_method_tab[i].func();
206
+
207
+ if (SSL_CTX_set_ssl_version(ctx, method) != 1)
208
+ ossl_raise(eSSLError, "SSL_CTX_set_ssl_version");
209
+
210
+ #if defined(HAVE_SSL_CTX_SET_MIN_PROTO_VERSION)
211
+ if (!SSL_CTX_set_min_proto_version(ctx, version))
212
+ ossl_raise(eSSLError, "SSL_CTX_set_min_proto_version");
213
+ if (!SSL_CTX_set_max_proto_version(ctx, version))
214
+ ossl_raise(eSSLError, "SSL_CTX_set_max_proto_version");
215
+ #endif
216
+ return ssl_method;
217
+ }
218
+ }
219
+
220
+ ossl_raise(rb_eArgError, "unknown SSL method `%"PRIsVALUE"'.", m);
221
+ }
222
+
223
+ static VALUE
224
+ ossl_call_client_cert_cb(VALUE obj)
225
+ {
226
+ VALUE cb, ary, cert, key;
227
+
228
+ cb = ossl_sslctx_get_client_cert_cb(ossl_ssl_get_ctx(obj));
229
+ if (NIL_P(cb))
230
+ return Qnil;
231
+
232
+ ary = rb_funcall(cb, rb_intern("call"), 1, obj);
233
+ Check_Type(ary, T_ARRAY);
234
+ GetX509CertPtr(cert = rb_ary_entry(ary, 0));
235
+ GetPrivPKeyPtr(key = rb_ary_entry(ary, 1));
236
+
237
+ return rb_ary_new3(2, cert, key);
238
+ }
239
+
240
+ static int
241
+ ossl_client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
242
+ {
243
+ VALUE obj, ret;
244
+
245
+ obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
246
+ ret = rb_protect(ossl_call_client_cert_cb, obj, NULL);
247
+ if (NIL_P(ret))
248
+ return 0;
249
+
250
+ *x509 = DupX509CertPtr(RARRAY_AREF(ret, 0));
251
+ *pkey = DupPKeyPtr(RARRAY_AREF(ret, 1));
252
+
253
+ return 1;
254
+ }
255
+
256
+ #if !defined(OPENSSL_NO_DH)
257
+ static VALUE
258
+ ossl_call_tmp_dh_callback(VALUE args)
259
+ {
260
+ VALUE cb, dh;
261
+ EVP_PKEY *pkey;
262
+
263
+ cb = rb_funcall(rb_ary_entry(args, 0), rb_intern("tmp_dh_callback"), 0);
264
+
265
+ if (NIL_P(cb)) return Qfalse;
266
+ dh = rb_apply(cb, rb_intern("call"), args);
267
+ pkey = GetPKeyPtr(dh);
268
+ if (EVP_PKEY_base_id(pkey) != EVP_PKEY_DH) return Qfalse;
269
+
270
+ return dh;
271
+ }
272
+
273
+ static DH*
274
+ ossl_tmp_dh_callback(SSL *ssl, int is_export, int keylength)
275
+ {
276
+ VALUE args, dh, rb_ssl;
277
+
278
+ rb_ssl = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
279
+
280
+ args = rb_ary_new_from_args(3, rb_ssl, INT2NUM(is_export), INT2NUM(keylength));
281
+
282
+ dh = rb_protect(ossl_call_tmp_dh_callback, args, NULL);
283
+ if (!RTEST(dh)) return NULL;
284
+ ossl_ssl_set_tmp_dh(rb_ssl, dh);
285
+
286
+ return EVP_PKEY_get0_DH(GetPKeyPtr(dh));
287
+ }
288
+ #endif /* OPENSSL_NO_DH */
289
+
290
+ #if !defined(OPENSSL_NO_EC) && defined(HAVE_SSL_CTX_SET_TMP_ECDH_CALLBACK)
291
+ static VALUE
292
+ ossl_call_tmp_ecdh_callback(VALUE args)
293
+ {
294
+ VALUE cb, ecdh;
295
+ EVP_PKEY *pkey;
296
+
297
+ cb = rb_funcall(rb_ary_entry(args, 0), rb_intern("tmp_ecdh_callback"), 0);
298
+
299
+ if (NIL_P(cb)) return Qfalse;
300
+ ecdh = rb_apply(cb, rb_intern("call"), args);
301
+ pkey = GetPKeyPtr(ecdh);
302
+ if (EVP_PKEY_base_id(pkey) != EVP_PKEY_EC) return Qfalse;
303
+
304
+ return ecdh;
305
+ }
306
+
307
+ static EC_KEY*
308
+ ossl_tmp_ecdh_callback(SSL *ssl, int is_export, int keylength)
309
+ {
310
+ VALUE args, ecdh, rb_ssl;
311
+
312
+ rb_ssl = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
313
+
314
+ args = rb_ary_new_from_args(3, rb_ssl, INT2NUM(is_export), INT2NUM(keylength));
315
+
316
+ ecdh = rb_protect(ossl_call_tmp_ecdh_callback, args, NULL);
317
+ if (!RTEST(ecdh)) return NULL;
318
+ ossl_ssl_set_tmp_ecdh(rb_ssl, ecdh);
319
+
320
+ return EVP_PKEY_get0_EC_KEY(GetPKeyPtr(ecdh));
321
+ }
322
+ #endif
323
+
324
+ static VALUE
325
+ call_verify_certificate_identity(VALUE ctx_v)
326
+ {
327
+ X509_STORE_CTX *ctx = (X509_STORE_CTX *)ctx_v;
328
+ SSL *ssl;
329
+ VALUE ssl_obj, hostname, cert_obj;
330
+
331
+ ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
332
+ ssl_obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
333
+ hostname = rb_attr_get(ssl_obj, rb_intern("@hostname"));
334
+
335
+ if (!RTEST(hostname)) {
336
+ rb_warning("verify_hostname requires hostname to be set");
337
+ return Qtrue;
338
+ }
339
+
340
+ cert_obj = ossl_x509_new(X509_STORE_CTX_get_current_cert(ctx));
341
+ return rb_funcall(mSSL, rb_intern("verify_certificate_identity"), 2,
342
+ cert_obj, hostname);
343
+ }
344
+
345
+ static int
346
+ ossl_ssl_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
347
+ {
348
+ VALUE cb, ssl_obj, verify_hostname, ret;
349
+ SSL *ssl;
350
+ int status;
351
+
352
+ ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
353
+ cb = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_vcb_idx);
354
+ ssl_obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
355
+ verify_hostname = ossl_sslctx_get_verify_hostname(ossl_ssl_get_ctx(ssl_obj));
356
+
357
+ if (preverify_ok && RTEST(verify_hostname) && !SSL_is_server(ssl) &&
358
+ !X509_STORE_CTX_get_error_depth(ctx)) {
359
+ ret = rb_protect(call_verify_certificate_identity, (VALUE)ctx, &status);
360
+ if (status) {
361
+ rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(status));
362
+ return 0;
363
+ }
364
+ preverify_ok = ret == Qtrue;
365
+ }
366
+
367
+ return ossl_verify_cb_call(cb, preverify_ok, ctx);
368
+ }
369
+
370
+ static VALUE
371
+ ossl_call_session_get_cb(VALUE ary)
372
+ {
373
+ VALUE ssl_obj, cb;
374
+
375
+ Check_Type(ary, T_ARRAY);
376
+ ssl_obj = rb_ary_entry(ary, 0);
377
+
378
+ cb = rb_funcall(ssl_obj, rb_intern("session_get_cb"), 0);
379
+ if (NIL_P(cb)) return Qnil;
380
+
381
+ return rb_funcall(cb, rb_intern("call"), 1, ary);
382
+ }
383
+
384
+ /* this method is currently only called for servers (in OpenSSL <= 0.9.8e) */
385
+ static SSL_SESSION *
386
+ #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
387
+ ossl_sslctx_session_get_cb(SSL *ssl, const unsigned char *buf, int len, int *copy)
388
+ #else
389
+ ossl_sslctx_session_get_cb(SSL *ssl, unsigned char *buf, int len, int *copy)
390
+ #endif
391
+ {
392
+ VALUE ary, ssl_obj, ret_obj;
393
+ SSL_SESSION *sess;
394
+ void *ptr;
395
+ int state = 0;
396
+
397
+ OSSL_Debug("SSL SESSION get callback entered");
398
+ if ((ptr = SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx)) == NULL)
399
+ return NULL;
400
+ ssl_obj = (VALUE)ptr;
401
+ ary = rb_ary_new2(2);
402
+ rb_ary_push(ary, ssl_obj);
403
+ rb_ary_push(ary, rb_str_new((const char *)buf, len));
404
+
405
+ ret_obj = rb_protect(ossl_call_session_get_cb, ary, &state);
406
+ if (state) {
407
+ rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(state));
408
+ return NULL;
409
+ }
410
+ if (!rb_obj_is_instance_of(ret_obj, cSSLSession))
411
+ return NULL;
412
+
413
+ SafeGetSSLSession(ret_obj, sess);
414
+ *copy = 1;
415
+
416
+ return sess;
417
+ }
418
+
419
+ static VALUE
420
+ ossl_call_session_new_cb(VALUE ary)
421
+ {
422
+ VALUE ssl_obj, cb;
423
+
424
+ Check_Type(ary, T_ARRAY);
425
+ ssl_obj = rb_ary_entry(ary, 0);
426
+
427
+ cb = rb_funcall(ssl_obj, rb_intern("session_new_cb"), 0);
428
+ if (NIL_P(cb)) return Qnil;
429
+
430
+ return rb_funcall(cb, rb_intern("call"), 1, ary);
431
+ }
432
+
433
+ /* return 1 normal. return 0 removes the session */
434
+ static int
435
+ ossl_sslctx_session_new_cb(SSL *ssl, SSL_SESSION *sess)
436
+ {
437
+ VALUE ary, ssl_obj, sess_obj;
438
+ void *ptr;
439
+ int state = 0;
440
+
441
+ OSSL_Debug("SSL SESSION new callback entered");
442
+
443
+ if ((ptr = SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx)) == NULL)
444
+ return 1;
445
+ ssl_obj = (VALUE)ptr;
446
+ sess_obj = rb_obj_alloc(cSSLSession);
447
+ SSL_SESSION_up_ref(sess);
448
+ DATA_PTR(sess_obj) = sess;
449
+
450
+ ary = rb_ary_new2(2);
451
+ rb_ary_push(ary, ssl_obj);
452
+ rb_ary_push(ary, sess_obj);
453
+
454
+ rb_protect(ossl_call_session_new_cb, ary, &state);
455
+ if (state) {
456
+ rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(state));
457
+ }
458
+
459
+ /*
460
+ * return 0 which means to OpenSSL that the session is still
461
+ * valid (since we created Ruby Session object) and was not freed by us
462
+ * with SSL_SESSION_free(). Call SSLContext#remove_session(sess) in
463
+ * session_get_cb block if you don't want OpenSSL to cache the session
464
+ * internally.
465
+ */
466
+ return 0;
467
+ }
468
+
469
+ static VALUE
470
+ ossl_call_session_remove_cb(VALUE ary)
471
+ {
472
+ VALUE sslctx_obj, cb;
473
+
474
+ Check_Type(ary, T_ARRAY);
475
+ sslctx_obj = rb_ary_entry(ary, 0);
476
+
477
+ cb = rb_iv_get(sslctx_obj, "@session_remove_cb");
478
+ if (NIL_P(cb)) return Qnil;
479
+
480
+ return rb_funcall(cb, rb_intern("call"), 1, ary);
481
+ }
482
+
483
+ static void
484
+ ossl_sslctx_session_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
485
+ {
486
+ VALUE ary, sslctx_obj, sess_obj;
487
+ void *ptr;
488
+ int state = 0;
489
+
490
+ OSSL_Debug("SSL SESSION remove callback entered");
491
+
492
+ if ((ptr = SSL_CTX_get_ex_data(ctx, ossl_ssl_ex_ptr_idx)) == NULL)
493
+ return;
494
+ sslctx_obj = (VALUE)ptr;
495
+ sess_obj = rb_obj_alloc(cSSLSession);
496
+ SSL_SESSION_up_ref(sess);
497
+ DATA_PTR(sess_obj) = sess;
498
+
499
+ ary = rb_ary_new2(2);
500
+ rb_ary_push(ary, sslctx_obj);
501
+ rb_ary_push(ary, sess_obj);
502
+
503
+ rb_protect(ossl_call_session_remove_cb, ary, &state);
504
+ if (state) {
505
+ /*
506
+ the SSL_CTX is frozen, nowhere to save state.
507
+ there is no common accessor method to check it either.
508
+ rb_ivar_set(sslctx_obj, ID_callback_state, INT2NUM(state));
509
+ */
510
+ }
511
+ }
512
+
513
+ static VALUE
514
+ ossl_sslctx_add_extra_chain_cert_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, arg))
515
+ {
516
+ X509 *x509;
517
+ SSL_CTX *ctx;
518
+
519
+ GetSSLCTX(arg, ctx);
520
+ x509 = DupX509CertPtr(i);
521
+ if(!SSL_CTX_add_extra_chain_cert(ctx, x509)){
522
+ ossl_raise(eSSLError, NULL);
523
+ }
524
+
525
+ return i;
526
+ }
527
+
528
+ static VALUE ossl_sslctx_setup(VALUE self);
529
+
530
+ #ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME
531
+ static VALUE
532
+ ossl_call_servername_cb(VALUE ary)
533
+ {
534
+ VALUE ssl_obj, sslctx_obj, cb, ret_obj;
535
+
536
+ Check_Type(ary, T_ARRAY);
537
+ ssl_obj = rb_ary_entry(ary, 0);
538
+
539
+ sslctx_obj = rb_iv_get(ssl_obj, "@context");
540
+ if (NIL_P(sslctx_obj)) return Qnil;
541
+ cb = rb_iv_get(sslctx_obj, "@servername_cb");
542
+ if (NIL_P(cb)) return Qnil;
543
+
544
+ ret_obj = rb_funcall(cb, rb_intern("call"), 1, ary);
545
+ if (rb_obj_is_kind_of(ret_obj, cSSLContext)) {
546
+ SSL *ssl;
547
+ SSL_CTX *ctx2;
548
+
549
+ ossl_sslctx_setup(ret_obj);
550
+ GetSSL(ssl_obj, ssl);
551
+ GetSSLCTX(ret_obj, ctx2);
552
+ SSL_set_SSL_CTX(ssl, ctx2);
553
+ rb_iv_set(ssl_obj, "@context", ret_obj);
554
+ } else if (!NIL_P(ret_obj)) {
555
+ ossl_raise(rb_eArgError, "servername_cb must return an OpenSSL::SSL::SSLContext object or nil");
556
+ }
557
+
558
+ return ret_obj;
559
+ }
560
+
561
+ static int
562
+ ssl_servername_cb(SSL *ssl, int *ad, void *arg)
563
+ {
564
+ VALUE ary, ssl_obj;
565
+ void *ptr;
566
+ int state = 0;
567
+ const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
568
+
569
+ if (!servername)
570
+ return SSL_TLSEXT_ERR_OK;
571
+
572
+ if ((ptr = SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx)) == NULL)
573
+ return SSL_TLSEXT_ERR_ALERT_FATAL;
574
+ ssl_obj = (VALUE)ptr;
575
+ ary = rb_ary_new2(2);
576
+ rb_ary_push(ary, ssl_obj);
577
+ rb_ary_push(ary, rb_str_new2(servername));
578
+
579
+ rb_protect(ossl_call_servername_cb, ary, &state);
580
+ if (state) {
581
+ rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(state));
582
+ return SSL_TLSEXT_ERR_ALERT_FATAL;
583
+ }
584
+
585
+ return SSL_TLSEXT_ERR_OK;
586
+ }
587
+ #endif
588
+
589
+ static void
590
+ ssl_renegotiation_cb(const SSL *ssl)
591
+ {
592
+ VALUE ssl_obj, sslctx_obj, cb;
593
+ void *ptr;
594
+
595
+ if ((ptr = SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx)) == NULL)
596
+ ossl_raise(eSSLError, "SSL object could not be retrieved");
597
+ ssl_obj = (VALUE)ptr;
598
+
599
+ sslctx_obj = rb_iv_get(ssl_obj, "@context");
600
+ if (NIL_P(sslctx_obj)) return;
601
+ cb = rb_iv_get(sslctx_obj, "@renegotiation_cb");
602
+ if (NIL_P(cb)) return;
603
+
604
+ (void) rb_funcall(cb, rb_intern("call"), 1, ssl_obj);
605
+ }
606
+
607
+ #if defined(HAVE_SSL_CTX_SET_NEXT_PROTO_SELECT_CB) || defined(HAVE_SSL_CTX_SET_ALPN_SELECT_CB)
608
+ static VALUE
609
+ ssl_npn_encode_protocol_i(VALUE cur, VALUE encoded)
610
+ {
611
+ int len = RSTRING_LENINT(cur);
612
+ char len_byte;
613
+ if (len < 1 || len > 255)
614
+ ossl_raise(eSSLError, "Advertised protocol must have length 1..255");
615
+ /* Encode the length byte */
616
+ len_byte = len;
617
+ rb_str_buf_cat(encoded, &len_byte, 1);
618
+ rb_str_buf_cat(encoded, RSTRING_PTR(cur), len);
619
+ return Qnil;
620
+ }
621
+
622
+ static VALUE
623
+ ssl_encode_npn_protocols(VALUE protocols)
624
+ {
625
+ VALUE encoded = rb_str_new(NULL, 0);
626
+ rb_iterate(rb_each, protocols, ssl_npn_encode_protocol_i, encoded);
627
+ return encoded;
628
+ }
629
+
630
+ static int
631
+ ssl_npn_select_cb_common(VALUE cb, const unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen)
632
+ {
633
+ VALUE selected;
634
+ long len;
635
+ VALUE protocols = rb_ary_new();
636
+ unsigned char l;
637
+ const unsigned char *in_end = in + inlen;
638
+
639
+ /* assume OpenSSL verifies this format */
640
+ /* The format is len_1|proto_1|...|len_n|proto_n */
641
+ while (in < in_end) {
642
+ l = *in++;
643
+ rb_ary_push(protocols, rb_str_new((const char *)in, l));
644
+ in += l;
645
+ }
646
+
647
+ selected = rb_funcall(cb, rb_intern("call"), 1, protocols);
648
+ StringValue(selected);
649
+ len = RSTRING_LEN(selected);
650
+ if (len < 1 || len >= 256) {
651
+ ossl_raise(eSSLError, "Selected protocol name must have length 1..255");
652
+ }
653
+ *out = (unsigned char *)RSTRING_PTR(selected);
654
+ *outlen = (unsigned char)len;
655
+
656
+ return SSL_TLSEXT_ERR_OK;
657
+ }
658
+
659
+ #ifdef HAVE_SSL_CTX_SET_NEXT_PROTO_SELECT_CB
660
+ static int
661
+ ssl_npn_advertise_cb(SSL *ssl, const unsigned char **out, unsigned int *outlen, void *arg)
662
+ {
663
+ VALUE protocols = (VALUE)arg;
664
+
665
+ *out = (const unsigned char *) RSTRING_PTR(protocols);
666
+ *outlen = RSTRING_LENINT(protocols);
667
+
668
+ return SSL_TLSEXT_ERR_OK;
669
+ }
670
+
671
+ static int
672
+ ssl_npn_select_cb(SSL *s, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg)
673
+ {
674
+ VALUE sslctx_obj, cb;
675
+
676
+ sslctx_obj = (VALUE) arg;
677
+ cb = rb_iv_get(sslctx_obj, "@npn_select_cb");
678
+
679
+ return ssl_npn_select_cb_common(cb, (const unsigned char **)out, outlen, in, inlen);
680
+ }
681
+ #endif
682
+
683
+ #ifdef HAVE_SSL_CTX_SET_ALPN_SELECT_CB
684
+ static int
685
+ ssl_alpn_select_cb(SSL *ssl, const unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg)
686
+ {
687
+ VALUE sslctx_obj, cb;
688
+
689
+ sslctx_obj = (VALUE) arg;
690
+ cb = rb_iv_get(sslctx_obj, "@alpn_select_cb");
691
+
692
+ return ssl_npn_select_cb_common(cb, out, outlen, in, inlen);
693
+ }
694
+ #endif
695
+ #endif /* HAVE_SSL_CTX_SET_NEXT_PROTO_SELECT_CB || HAVE_SSL_CTX_SET_ALPN_SELECT_CB */
696
+
697
+ /* This function may serve as the entry point to support further callbacks. */
698
+ static void
699
+ ssl_info_cb(const SSL *ssl, int where, int val)
700
+ {
701
+ int is_server = SSL_is_server((SSL *)ssl);
702
+
703
+ if (is_server && where & SSL_CB_HANDSHAKE_START) {
704
+ ssl_renegotiation_cb(ssl);
705
+ }
706
+ }
707
+
708
+ /*
709
+ * Gets various OpenSSL options.
710
+ */
711
+ static VALUE
712
+ ossl_sslctx_get_options(VALUE self)
713
+ {
714
+ SSL_CTX *ctx;
715
+ GetSSLCTX(self, ctx);
716
+ return LONG2NUM(SSL_CTX_get_options(ctx));
717
+ }
718
+
719
+ /*
720
+ * Sets various OpenSSL options.
721
+ */
722
+ static VALUE
723
+ ossl_sslctx_set_options(VALUE self, VALUE options)
724
+ {
725
+ SSL_CTX *ctx;
726
+
727
+ rb_check_frozen(self);
728
+ GetSSLCTX(self, ctx);
729
+
730
+ SSL_CTX_clear_options(ctx, SSL_CTX_get_options(ctx));
731
+
732
+ if (NIL_P(options)) {
733
+ SSL_CTX_set_options(ctx, SSL_OP_ALL);
734
+ } else {
735
+ SSL_CTX_set_options(ctx, NUM2LONG(options));
736
+ }
737
+
738
+ return self;
739
+ }
740
+
741
+ /*
742
+ * call-seq:
743
+ * ctx.setup => Qtrue # first time
744
+ * ctx.setup => nil # thereafter
745
+ *
746
+ * This method is called automatically when a new SSLSocket is created.
747
+ * However, it is not thread-safe and must be called before creating
748
+ * SSLSocket objects in a multi-threaded program.
749
+ */
750
+ static VALUE
751
+ ossl_sslctx_setup(VALUE self)
752
+ {
753
+ SSL_CTX *ctx;
754
+ X509 *cert = NULL, *client_ca = NULL;
755
+ EVP_PKEY *key = NULL;
756
+ char *ca_path = NULL, *ca_file = NULL;
757
+ int verify_mode;
758
+ long i;
759
+ VALUE val;
760
+
761
+ if(OBJ_FROZEN(self)) return Qnil;
762
+ GetSSLCTX(self, ctx);
763
+
764
+ #if !defined(OPENSSL_NO_DH)
765
+ SSL_CTX_set_tmp_dh_callback(ctx, ossl_tmp_dh_callback);
766
+ #endif
767
+
768
+ #if !defined(OPENSSL_NO_EC)
769
+ /* We added SSLContext#tmp_ecdh_callback= in Ruby 2.3.0,
770
+ * but SSL_CTX_set_tmp_ecdh_callback() was removed in OpenSSL 1.1.0. */
771
+ if (RTEST(ossl_sslctx_get_tmp_ecdh_cb(self))) {
772
+ # if defined(HAVE_SSL_CTX_SET_TMP_ECDH_CALLBACK)
773
+ rb_warn("#tmp_ecdh_callback= is deprecated; use #ecdh_curves= instead");
774
+ SSL_CTX_set_tmp_ecdh_callback(ctx, ossl_tmp_ecdh_callback);
775
+ # if defined(HAVE_SSL_CTX_SET_ECDH_AUTO)
776
+ /* tmp_ecdh_callback and ecdh_auto conflict; OpenSSL ignores
777
+ * tmp_ecdh_callback. So disable ecdh_auto. */
778
+ if (!SSL_CTX_set_ecdh_auto(ctx, 0))
779
+ ossl_raise(eSSLError, "SSL_CTX_set_ecdh_auto");
780
+ # endif
781
+ # else
782
+ ossl_raise(eSSLError, "OpenSSL does not support tmp_ecdh_callback; "
783
+ "use #ecdh_curves= instead");
784
+ # endif
785
+ }
786
+ #endif /* OPENSSL_NO_EC */
787
+
788
+ val = ossl_sslctx_get_cert_store(self);
789
+ if (!NIL_P(val)) {
790
+ X509_STORE *store = GetX509StorePtr(val); /* NO NEED TO DUP */
791
+ SSL_CTX_set_cert_store(ctx, store);
792
+ #if !defined(HAVE_X509_STORE_UP_REF)
793
+ /*
794
+ * WORKAROUND:
795
+ * X509_STORE can count references, but
796
+ * X509_STORE_free() doesn't care it.
797
+ * So we won't increment it but mark it by ex_data.
798
+ */
799
+ SSL_CTX_set_ex_data(ctx, ossl_ssl_ex_store_p, (void *)1);
800
+ #else /* Fixed in OpenSSL 1.0.2; bff9ce4db38b (master), 5b4b9ce976fc (1.0.2) */
801
+ X509_STORE_up_ref(store);
802
+ #endif
803
+ }
804
+
805
+ val = ossl_sslctx_get_extra_cert(self);
806
+ if(!NIL_P(val)){
807
+ rb_block_call(val, rb_intern("each"), 0, 0, ossl_sslctx_add_extra_chain_cert_i, self);
808
+ }
809
+
810
+ /* private key may be bundled in certificate file. */
811
+ val = ossl_sslctx_get_cert(self);
812
+ cert = NIL_P(val) ? NULL : GetX509CertPtr(val); /* NO DUP NEEDED */
813
+ val = ossl_sslctx_get_key(self);
814
+ key = NIL_P(val) ? NULL : GetPrivPKeyPtr(val); /* NO DUP NEEDED */
815
+ if (cert && key) {
816
+ if (!SSL_CTX_use_certificate(ctx, cert)) {
817
+ /* Adds a ref => Safe to FREE */
818
+ ossl_raise(eSSLError, "SSL_CTX_use_certificate");
819
+ }
820
+ if (!SSL_CTX_use_PrivateKey(ctx, key)) {
821
+ /* Adds a ref => Safe to FREE */
822
+ ossl_raise(eSSLError, "SSL_CTX_use_PrivateKey");
823
+ }
824
+ if (!SSL_CTX_check_private_key(ctx)) {
825
+ ossl_raise(eSSLError, "SSL_CTX_check_private_key");
826
+ }
827
+ }
828
+
829
+ val = ossl_sslctx_get_client_ca(self);
830
+ if(!NIL_P(val)){
831
+ if (RB_TYPE_P(val, T_ARRAY)) {
832
+ for(i = 0; i < RARRAY_LEN(val); i++){
833
+ client_ca = GetX509CertPtr(RARRAY_AREF(val, i));
834
+ if (!SSL_CTX_add_client_CA(ctx, client_ca)){
835
+ /* Copies X509_NAME => FREE it. */
836
+ ossl_raise(eSSLError, "SSL_CTX_add_client_CA");
837
+ }
838
+ }
839
+ }
840
+ else{
841
+ client_ca = GetX509CertPtr(val); /* NO DUP NEEDED. */
842
+ if (!SSL_CTX_add_client_CA(ctx, client_ca)){
843
+ /* Copies X509_NAME => FREE it. */
844
+ ossl_raise(eSSLError, "SSL_CTX_add_client_CA");
845
+ }
846
+ }
847
+ }
848
+
849
+ val = ossl_sslctx_get_ca_file(self);
850
+ ca_file = NIL_P(val) ? NULL : StringValueCStr(val);
851
+ val = ossl_sslctx_get_ca_path(self);
852
+ ca_path = NIL_P(val) ? NULL : StringValueCStr(val);
853
+ if(ca_file || ca_path){
854
+ if (!SSL_CTX_load_verify_locations(ctx, ca_file, ca_path))
855
+ rb_warning("can't set verify locations");
856
+ }
857
+
858
+ val = ossl_sslctx_get_verify_mode(self);
859
+ verify_mode = NIL_P(val) ? SSL_VERIFY_NONE : NUM2INT(val);
860
+ SSL_CTX_set_verify(ctx, verify_mode, ossl_ssl_verify_callback);
861
+ if (RTEST(ossl_sslctx_get_client_cert_cb(self)))
862
+ SSL_CTX_set_client_cert_cb(ctx, ossl_client_cert_cb);
863
+
864
+ val = ossl_sslctx_get_timeout(self);
865
+ if(!NIL_P(val)) SSL_CTX_set_timeout(ctx, NUM2LONG(val));
866
+
867
+ val = ossl_sslctx_get_verify_dep(self);
868
+ if(!NIL_P(val)) SSL_CTX_set_verify_depth(ctx, NUM2INT(val));
869
+
870
+ #ifdef HAVE_SSL_CTX_SET_NEXT_PROTO_SELECT_CB
871
+ val = rb_iv_get(self, "@npn_protocols");
872
+ if (!NIL_P(val)) {
873
+ VALUE encoded = ssl_encode_npn_protocols(val);
874
+ SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_npn_advertise_cb, (void *)encoded);
875
+ OSSL_Debug("SSL NPN advertise callback added");
876
+ }
877
+ if (RTEST(rb_iv_get(self, "@npn_select_cb"))) {
878
+ SSL_CTX_set_next_proto_select_cb(ctx, ssl_npn_select_cb, (void *) self);
879
+ OSSL_Debug("SSL NPN select callback added");
880
+ }
881
+ #endif
882
+
883
+ #ifdef HAVE_SSL_CTX_SET_ALPN_SELECT_CB
884
+ val = rb_iv_get(self, "@alpn_protocols");
885
+ if (!NIL_P(val)) {
886
+ VALUE rprotos = ssl_encode_npn_protocols(val);
887
+ SSL_CTX_set_alpn_protos(ctx, (unsigned char *)RSTRING_PTR(rprotos), RSTRING_LENINT(rprotos));
888
+ OSSL_Debug("SSL ALPN values added");
889
+ }
890
+ if (RTEST(rb_iv_get(self, "@alpn_select_cb"))) {
891
+ SSL_CTX_set_alpn_select_cb(ctx, ssl_alpn_select_cb, (void *) self);
892
+ OSSL_Debug("SSL ALPN select callback added");
893
+ }
894
+ #endif
895
+
896
+ rb_obj_freeze(self);
897
+
898
+ val = ossl_sslctx_get_sess_id_ctx(self);
899
+ if (!NIL_P(val)){
900
+ StringValue(val);
901
+ if (!SSL_CTX_set_session_id_context(ctx, (unsigned char *)RSTRING_PTR(val),
902
+ RSTRING_LENINT(val))){
903
+ ossl_raise(eSSLError, "SSL_CTX_set_session_id_context");
904
+ }
905
+ }
906
+
907
+ if (RTEST(rb_iv_get(self, "@session_get_cb"))) {
908
+ SSL_CTX_sess_set_get_cb(ctx, ossl_sslctx_session_get_cb);
909
+ OSSL_Debug("SSL SESSION get callback added");
910
+ }
911
+ if (RTEST(rb_iv_get(self, "@session_new_cb"))) {
912
+ SSL_CTX_sess_set_new_cb(ctx, ossl_sslctx_session_new_cb);
913
+ OSSL_Debug("SSL SESSION new callback added");
914
+ }
915
+ if (RTEST(rb_iv_get(self, "@session_remove_cb"))) {
916
+ SSL_CTX_sess_set_remove_cb(ctx, ossl_sslctx_session_remove_cb);
917
+ OSSL_Debug("SSL SESSION remove callback added");
918
+ }
919
+
920
+ #ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME
921
+ val = rb_iv_get(self, "@servername_cb");
922
+ if (!NIL_P(val)) {
923
+ SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb);
924
+ OSSL_Debug("SSL TLSEXT servername callback added");
925
+ }
926
+ #endif
927
+
928
+ return Qtrue;
929
+ }
930
+
931
+ static VALUE
932
+ ossl_ssl_cipher_to_ary(const SSL_CIPHER *cipher)
933
+ {
934
+ VALUE ary;
935
+ int bits, alg_bits;
936
+
937
+ ary = rb_ary_new2(4);
938
+ rb_ary_push(ary, rb_str_new2(SSL_CIPHER_get_name(cipher)));
939
+ rb_ary_push(ary, rb_str_new2(SSL_CIPHER_get_version(cipher)));
940
+ bits = SSL_CIPHER_get_bits(cipher, &alg_bits);
941
+ rb_ary_push(ary, INT2NUM(bits));
942
+ rb_ary_push(ary, INT2NUM(alg_bits));
943
+
944
+ return ary;
945
+ }
946
+
947
+ /*
948
+ * call-seq:
949
+ * ctx.ciphers => [[name, version, bits, alg_bits], ...]
950
+ *
951
+ * The list of cipher suites configured for this context.
952
+ */
953
+ static VALUE
954
+ ossl_sslctx_get_ciphers(VALUE self)
955
+ {
956
+ SSL_CTX *ctx;
957
+ STACK_OF(SSL_CIPHER) *ciphers;
958
+ const SSL_CIPHER *cipher;
959
+ VALUE ary;
960
+ int i, num;
961
+
962
+ GetSSLCTX(self, ctx);
963
+ if(!ctx){
964
+ rb_warning("SSL_CTX is not initialized.");
965
+ return Qnil;
966
+ }
967
+ ciphers = SSL_CTX_get_ciphers(ctx);
968
+
969
+ if (!ciphers)
970
+ return rb_ary_new();
971
+
972
+ num = sk_SSL_CIPHER_num(ciphers);
973
+ ary = rb_ary_new2(num);
974
+ for(i = 0; i < num; i++){
975
+ cipher = sk_SSL_CIPHER_value(ciphers, i);
976
+ rb_ary_push(ary, ossl_ssl_cipher_to_ary(cipher));
977
+ }
978
+ return ary;
979
+ }
980
+
981
+ /*
982
+ * call-seq:
983
+ * ctx.ciphers = "cipher1:cipher2:..."
984
+ * ctx.ciphers = [name, ...]
985
+ * ctx.ciphers = [[name, version, bits, alg_bits], ...]
986
+ *
987
+ * Sets the list of available cipher suites for this context. Note in a server
988
+ * context some ciphers require the appropriate certificates. For example, an
989
+ * RSA cipher suite can only be chosen when an RSA certificate is available.
990
+ */
991
+ static VALUE
992
+ ossl_sslctx_set_ciphers(VALUE self, VALUE v)
993
+ {
994
+ SSL_CTX *ctx;
995
+ VALUE str, elem;
996
+ int i;
997
+
998
+ rb_check_frozen(self);
999
+ if (NIL_P(v))
1000
+ return v;
1001
+ else if (RB_TYPE_P(v, T_ARRAY)) {
1002
+ str = rb_str_new(0, 0);
1003
+ for (i = 0; i < RARRAY_LEN(v); i++) {
1004
+ elem = rb_ary_entry(v, i);
1005
+ if (RB_TYPE_P(elem, T_ARRAY)) elem = rb_ary_entry(elem, 0);
1006
+ elem = rb_String(elem);
1007
+ rb_str_append(str, elem);
1008
+ if (i < RARRAY_LEN(v)-1) rb_str_cat2(str, ":");
1009
+ }
1010
+ } else {
1011
+ str = v;
1012
+ StringValue(str);
1013
+ }
1014
+
1015
+ GetSSLCTX(self, ctx);
1016
+ if(!ctx){
1017
+ ossl_raise(eSSLError, "SSL_CTX is not initialized.");
1018
+ return Qnil;
1019
+ }
1020
+ if (!SSL_CTX_set_cipher_list(ctx, StringValueCStr(str))) {
1021
+ ossl_raise(eSSLError, "SSL_CTX_set_cipher_list");
1022
+ }
1023
+
1024
+ return v;
1025
+ }
1026
+
1027
+ #if !defined(OPENSSL_NO_EC)
1028
+ /*
1029
+ * call-seq:
1030
+ * ctx.ecdh_curves = curve_list -> curve_list
1031
+ *
1032
+ * Sets the list of "supported elliptic curves" for this context.
1033
+ *
1034
+ * For a TLS client, the list is directly used in the Supported Elliptic Curves
1035
+ * Extension. For a server, the list is used by OpenSSL to determine the set of
1036
+ * shared curves. OpenSSL will pick the most appropriate one from it.
1037
+ *
1038
+ * Note that this works differently with old OpenSSL (<= 1.0.1). Only one curve
1039
+ * can be set, and this has no effect for TLS clients.
1040
+ *
1041
+ * === Example
1042
+ * ctx1 = OpenSSL::SSL::SSLContext.new
1043
+ * ctx1.ecdh_curves = "X25519:P-256:P-224"
1044
+ * svr = OpenSSL::SSL::SSLServer.new(tcp_svr, ctx1)
1045
+ * Thread.new { svr.accept }
1046
+ *
1047
+ * ctx2 = OpenSSL::SSL::SSLContext.new
1048
+ * ctx2.ecdh_curves = "P-256"
1049
+ * cli = OpenSSL::SSL::SSLSocket.new(tcp_sock, ctx2)
1050
+ * cli.connect
1051
+ *
1052
+ * p cli.tmp_key.group.curve_name
1053
+ * # => "prime256v1" (is an alias for NIST P-256)
1054
+ */
1055
+ static VALUE
1056
+ ossl_sslctx_set_ecdh_curves(VALUE self, VALUE arg)
1057
+ {
1058
+ SSL_CTX *ctx;
1059
+
1060
+ rb_check_frozen(self);
1061
+ GetSSLCTX(self, ctx);
1062
+ StringValueCStr(arg);
1063
+
1064
+ #if defined(HAVE_SSL_CTX_SET1_CURVES_LIST)
1065
+ if (!SSL_CTX_set1_curves_list(ctx, RSTRING_PTR(arg)))
1066
+ ossl_raise(eSSLError, NULL);
1067
+ #else
1068
+ /* OpenSSL does not have SSL_CTX_set1_curves_list()... Fallback to
1069
+ * SSL_CTX_set_tmp_ecdh(). So only the first curve is used. */
1070
+ {
1071
+ VALUE curve, splitted;
1072
+ EC_KEY *ec;
1073
+ int nid;
1074
+
1075
+ splitted = rb_str_split(arg, ":");
1076
+ if (!RARRAY_LEN(splitted))
1077
+ ossl_raise(eSSLError, "invalid input format");
1078
+ curve = RARRAY_AREF(splitted, 0);
1079
+ StringValueCStr(curve);
1080
+
1081
+ /* SSL_CTX_set1_curves_list() accepts NIST names */
1082
+ nid = EC_curve_nist2nid(RSTRING_PTR(curve));
1083
+ if (nid == NID_undef)
1084
+ nid = OBJ_txt2nid(RSTRING_PTR(curve));
1085
+ if (nid == NID_undef)
1086
+ ossl_raise(eSSLError, "unknown curve name");
1087
+
1088
+ ec = EC_KEY_new_by_curve_name(nid);
1089
+ if (!ec)
1090
+ ossl_raise(eSSLError, NULL);
1091
+ EC_KEY_set_asn1_flag(ec, OPENSSL_EC_NAMED_CURVE);
1092
+ if (!SSL_CTX_set_tmp_ecdh(ctx, ec)) {
1093
+ EC_KEY_free(ec);
1094
+ ossl_raise(eSSLError, "SSL_CTX_set_tmp_ecdh");
1095
+ }
1096
+ EC_KEY_free(ec);
1097
+ # if defined(HAVE_SSL_CTX_SET_ECDH_AUTO)
1098
+ /* tmp_ecdh and ecdh_auto conflict. tmp_ecdh is ignored when ecdh_auto
1099
+ * is enabled. So disable ecdh_auto. */
1100
+ if (!SSL_CTX_set_ecdh_auto(ctx, 0))
1101
+ ossl_raise(eSSLError, "SSL_CTX_set_ecdh_auto");
1102
+ # endif
1103
+ }
1104
+ #endif
1105
+
1106
+ return arg;
1107
+ }
1108
+ #else
1109
+ #define ossl_sslctx_set_ecdh_curves rb_f_notimplement
1110
+ #endif
1111
+
1112
+ /*
1113
+ * call-seq:
1114
+ * ctx.security_level -> Integer
1115
+ *
1116
+ * Returns the security level for the context.
1117
+ *
1118
+ * See also OpenSSL::SSL::SSLContext#security_level=.
1119
+ */
1120
+ static VALUE
1121
+ ossl_sslctx_get_security_level(VALUE self)
1122
+ {
1123
+ SSL_CTX *ctx;
1124
+
1125
+ GetSSLCTX(self, ctx);
1126
+
1127
+ #if defined(HAVE_SSL_CTX_GET_SECURITY_LEVEL)
1128
+ return INT2NUM(SSL_CTX_get_security_level(ctx));
1129
+ #else
1130
+ (void)ctx;
1131
+ return INT2FIX(0);
1132
+ #endif
1133
+ }
1134
+
1135
+ /*
1136
+ * call-seq:
1137
+ * ctx.security_level = integer
1138
+ *
1139
+ * Sets the security level for the context. OpenSSL limits parameters according
1140
+ * to the level. The "parameters" include: ciphersuites, curves, key sizes,
1141
+ * certificate signature algorithms, protocol version and so on. For example,
1142
+ * level 1 rejects parameters offering below 80 bits of security, such as
1143
+ * ciphersuites using MD5 for the MAC or RSA keys shorter than 1024 bits.
1144
+ *
1145
+ * Note that attempts to set such parameters with insufficient security are
1146
+ * also blocked. You need to lower the level first.
1147
+ *
1148
+ * This feature is not supported in OpenSSL < 1.1.0, and setting the level to
1149
+ * other than 0 will raise NotImplementedError. Level 0 means everything is
1150
+ * permitted, the same behavior as previous versions of OpenSSL.
1151
+ *
1152
+ * See the manpage of SSL_CTX_set_security_level(3) for details.
1153
+ */
1154
+ static VALUE
1155
+ ossl_sslctx_set_security_level(VALUE self, VALUE value)
1156
+ {
1157
+ SSL_CTX *ctx;
1158
+
1159
+ rb_check_frozen(self);
1160
+ GetSSLCTX(self, ctx);
1161
+
1162
+ #if defined(HAVE_SSL_CTX_GET_SECURITY_LEVEL)
1163
+ SSL_CTX_set_security_level(ctx, NUM2INT(value));
1164
+ #else
1165
+ (void)ctx;
1166
+ if (NUM2INT(value) != 0)
1167
+ ossl_raise(rb_eNotImpError, "setting security level to other than 0 is "
1168
+ "not supported in this version of OpenSSL");
1169
+ #endif
1170
+
1171
+ return value;
1172
+ }
1173
+
1174
+ /*
1175
+ * call-seq:
1176
+ * ctx.session_add(session) -> true | false
1177
+ *
1178
+ * Adds +session+ to the session cache.
1179
+ */
1180
+ static VALUE
1181
+ ossl_sslctx_session_add(VALUE self, VALUE arg)
1182
+ {
1183
+ SSL_CTX *ctx;
1184
+ SSL_SESSION *sess;
1185
+
1186
+ GetSSLCTX(self, ctx);
1187
+ SafeGetSSLSession(arg, sess);
1188
+
1189
+ return SSL_CTX_add_session(ctx, sess) == 1 ? Qtrue : Qfalse;
1190
+ }
1191
+
1192
+ /*
1193
+ * call-seq:
1194
+ * ctx.session_remove(session) -> true | false
1195
+ *
1196
+ * Removes +session+ from the session cache.
1197
+ */
1198
+ static VALUE
1199
+ ossl_sslctx_session_remove(VALUE self, VALUE arg)
1200
+ {
1201
+ SSL_CTX *ctx;
1202
+ SSL_SESSION *sess;
1203
+
1204
+ GetSSLCTX(self, ctx);
1205
+ SafeGetSSLSession(arg, sess);
1206
+
1207
+ return SSL_CTX_remove_session(ctx, sess) == 1 ? Qtrue : Qfalse;
1208
+ }
1209
+
1210
+ /*
1211
+ * call-seq:
1212
+ * ctx.session_cache_mode -> Integer
1213
+ *
1214
+ * The current session cache mode.
1215
+ */
1216
+ static VALUE
1217
+ ossl_sslctx_get_session_cache_mode(VALUE self)
1218
+ {
1219
+ SSL_CTX *ctx;
1220
+
1221
+ GetSSLCTX(self, ctx);
1222
+
1223
+ return LONG2NUM(SSL_CTX_get_session_cache_mode(ctx));
1224
+ }
1225
+
1226
+ /*
1227
+ * call-seq:
1228
+ * ctx.session_cache_mode=(integer) -> Integer
1229
+ *
1230
+ * Sets the SSL session cache mode. Bitwise-or together the desired
1231
+ * SESSION_CACHE_* constants to set. See SSL_CTX_set_session_cache_mode(3) for
1232
+ * details.
1233
+ */
1234
+ static VALUE
1235
+ ossl_sslctx_set_session_cache_mode(VALUE self, VALUE arg)
1236
+ {
1237
+ SSL_CTX *ctx;
1238
+
1239
+ GetSSLCTX(self, ctx);
1240
+
1241
+ SSL_CTX_set_session_cache_mode(ctx, NUM2LONG(arg));
1242
+
1243
+ return arg;
1244
+ }
1245
+
1246
+ /*
1247
+ * call-seq:
1248
+ * ctx.session_cache_size -> Integer
1249
+ *
1250
+ * Returns the current session cache size. Zero is used to represent an
1251
+ * unlimited cache size.
1252
+ */
1253
+ static VALUE
1254
+ ossl_sslctx_get_session_cache_size(VALUE self)
1255
+ {
1256
+ SSL_CTX *ctx;
1257
+
1258
+ GetSSLCTX(self, ctx);
1259
+
1260
+ return LONG2NUM(SSL_CTX_sess_get_cache_size(ctx));
1261
+ }
1262
+
1263
+ /*
1264
+ * call-seq:
1265
+ * ctx.session_cache_size=(integer) -> Integer
1266
+ *
1267
+ * Sets the session cache size. Returns the previously valid session cache
1268
+ * size. Zero is used to represent an unlimited session cache size.
1269
+ */
1270
+ static VALUE
1271
+ ossl_sslctx_set_session_cache_size(VALUE self, VALUE arg)
1272
+ {
1273
+ SSL_CTX *ctx;
1274
+
1275
+ GetSSLCTX(self, ctx);
1276
+
1277
+ SSL_CTX_sess_set_cache_size(ctx, NUM2LONG(arg));
1278
+
1279
+ return arg;
1280
+ }
1281
+
1282
+ /*
1283
+ * call-seq:
1284
+ * ctx.session_cache_stats -> Hash
1285
+ *
1286
+ * Returns a Hash containing the following keys:
1287
+ *
1288
+ * :accept:: Number of started SSL/TLS handshakes in server mode
1289
+ * :accept_good:: Number of established SSL/TLS sessions in server mode
1290
+ * :accept_renegotiate:: Number of start renegotiations in server mode
1291
+ * :cache_full:: Number of sessions that were removed due to cache overflow
1292
+ * :cache_hits:: Number of successfully reused connections
1293
+ * :cache_misses:: Number of sessions proposed by clients that were not found
1294
+ * in the cache
1295
+ * :cache_num:: Number of sessions in the internal session cache
1296
+ * :cb_hits:: Number of sessions retrieved from the external cache in server
1297
+ * mode
1298
+ * :connect:: Number of started SSL/TLS handshakes in client mode
1299
+ * :connect_good:: Number of established SSL/TLS sessions in client mode
1300
+ * :connect_renegotiate:: Number of start renegotiations in client mode
1301
+ * :timeouts:: Number of sessions proposed by clients that were found in the
1302
+ * cache but had expired due to timeouts
1303
+ */
1304
+ static VALUE
1305
+ ossl_sslctx_get_session_cache_stats(VALUE self)
1306
+ {
1307
+ SSL_CTX *ctx;
1308
+ VALUE hash;
1309
+
1310
+ GetSSLCTX(self, ctx);
1311
+
1312
+ hash = rb_hash_new();
1313
+ rb_hash_aset(hash, ID2SYM(rb_intern("cache_num")), LONG2NUM(SSL_CTX_sess_number(ctx)));
1314
+ rb_hash_aset(hash, ID2SYM(rb_intern("connect")), LONG2NUM(SSL_CTX_sess_connect(ctx)));
1315
+ rb_hash_aset(hash, ID2SYM(rb_intern("connect_good")), LONG2NUM(SSL_CTX_sess_connect_good(ctx)));
1316
+ rb_hash_aset(hash, ID2SYM(rb_intern("connect_renegotiate")), LONG2NUM(SSL_CTX_sess_connect_renegotiate(ctx)));
1317
+ rb_hash_aset(hash, ID2SYM(rb_intern("accept")), LONG2NUM(SSL_CTX_sess_accept(ctx)));
1318
+ rb_hash_aset(hash, ID2SYM(rb_intern("accept_good")), LONG2NUM(SSL_CTX_sess_accept_good(ctx)));
1319
+ rb_hash_aset(hash, ID2SYM(rb_intern("accept_renegotiate")), LONG2NUM(SSL_CTX_sess_accept_renegotiate(ctx)));
1320
+ rb_hash_aset(hash, ID2SYM(rb_intern("cache_hits")), LONG2NUM(SSL_CTX_sess_hits(ctx)));
1321
+ rb_hash_aset(hash, ID2SYM(rb_intern("cb_hits")), LONG2NUM(SSL_CTX_sess_cb_hits(ctx)));
1322
+ rb_hash_aset(hash, ID2SYM(rb_intern("cache_misses")), LONG2NUM(SSL_CTX_sess_misses(ctx)));
1323
+ rb_hash_aset(hash, ID2SYM(rb_intern("cache_full")), LONG2NUM(SSL_CTX_sess_cache_full(ctx)));
1324
+ rb_hash_aset(hash, ID2SYM(rb_intern("timeouts")), LONG2NUM(SSL_CTX_sess_timeouts(ctx)));
1325
+
1326
+ return hash;
1327
+ }
1328
+
1329
+
1330
+ /*
1331
+ * call-seq:
1332
+ * ctx.flush_sessions(time | nil) -> self
1333
+ *
1334
+ * Removes sessions in the internal cache that have expired at +time+.
1335
+ */
1336
+ static VALUE
1337
+ ossl_sslctx_flush_sessions(int argc, VALUE *argv, VALUE self)
1338
+ {
1339
+ VALUE arg1;
1340
+ SSL_CTX *ctx;
1341
+ time_t tm = 0;
1342
+
1343
+ rb_scan_args(argc, argv, "01", &arg1);
1344
+
1345
+ GetSSLCTX(self, ctx);
1346
+
1347
+ if (NIL_P(arg1)) {
1348
+ tm = time(0);
1349
+ } else if (rb_obj_is_instance_of(arg1, rb_cTime)) {
1350
+ tm = NUM2LONG(rb_funcall(arg1, rb_intern("to_i"), 0));
1351
+ } else {
1352
+ ossl_raise(rb_eArgError, "arg must be Time or nil");
1353
+ }
1354
+
1355
+ SSL_CTX_flush_sessions(ctx, (long)tm);
1356
+
1357
+ return self;
1358
+ }
1359
+
1360
+ /*
1361
+ * SSLSocket class
1362
+ */
1363
+ #ifndef OPENSSL_NO_SOCK
1364
+ static inline int
1365
+ ssl_started(SSL *ssl)
1366
+ {
1367
+ /* the FD is set in ossl_ssl_setup(), called by #connect or #accept */
1368
+ return SSL_get_fd(ssl) >= 0;
1369
+ }
1370
+
1371
+ static void
1372
+ ossl_ssl_shutdown(SSL *ssl)
1373
+ {
1374
+ int i;
1375
+
1376
+ /* 4 is from SSL_smart_shutdown() of mod_ssl.c (v2.2.19) */
1377
+ /* It says max 2x pending + 2x data = 4 */
1378
+ for (i = 0; i < 4; ++i) {
1379
+ /*
1380
+ * Ignore the case SSL_shutdown returns -1. Empty handshake_func
1381
+ * must not happen.
1382
+ */
1383
+ if (SSL_shutdown(ssl) != 0)
1384
+ break;
1385
+ }
1386
+ ossl_clear_error();
1387
+ }
1388
+
1389
+ static void
1390
+ ossl_ssl_free(void *ssl)
1391
+ {
1392
+ SSL_free(ssl);
1393
+ }
1394
+
1395
+ const rb_data_type_t ossl_ssl_type = {
1396
+ "OpenSSL/SSL",
1397
+ {
1398
+ 0, ossl_ssl_free,
1399
+ },
1400
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
1401
+ };
1402
+
1403
+ static VALUE
1404
+ ossl_ssl_s_alloc(VALUE klass)
1405
+ {
1406
+ return TypedData_Wrap_Struct(klass, &ossl_ssl_type, NULL);
1407
+ }
1408
+
1409
+ /*
1410
+ * call-seq:
1411
+ * SSLSocket.new(io) => aSSLSocket
1412
+ * SSLSocket.new(io, ctx) => aSSLSocket
1413
+ *
1414
+ * Creates a new SSL socket from +io+ which must be a real IO object (not an
1415
+ * IO-like object that responds to read/write).
1416
+ *
1417
+ * If +ctx+ is provided the SSL Sockets initial params will be taken from
1418
+ * the context.
1419
+ *
1420
+ * The OpenSSL::Buffering module provides additional IO methods.
1421
+ *
1422
+ * This method will freeze the SSLContext if one is provided;
1423
+ * however, session management is still allowed in the frozen SSLContext.
1424
+ */
1425
+ static VALUE
1426
+ ossl_ssl_initialize(int argc, VALUE *argv, VALUE self)
1427
+ {
1428
+ VALUE io, v_ctx, verify_cb;
1429
+ SSL *ssl;
1430
+ SSL_CTX *ctx;
1431
+
1432
+ TypedData_Get_Struct(self, SSL, &ossl_ssl_type, ssl);
1433
+ if (ssl)
1434
+ ossl_raise(eSSLError, "SSL already initialized");
1435
+
1436
+ if (rb_scan_args(argc, argv, "11", &io, &v_ctx) == 1)
1437
+ v_ctx = rb_funcall(cSSLContext, rb_intern("new"), 0);
1438
+
1439
+ GetSSLCTX(v_ctx, ctx);
1440
+ ossl_ssl_set_ctx(self, v_ctx);
1441
+ ossl_sslctx_setup(v_ctx);
1442
+
1443
+ if (rb_respond_to(io, rb_intern("nonblock=")))
1444
+ rb_funcall(io, rb_intern("nonblock="), 1, Qtrue);
1445
+ ossl_ssl_set_io(self, io);
1446
+
1447
+ ossl_ssl_set_sync_close(self, Qfalse);
1448
+
1449
+ ssl = SSL_new(ctx);
1450
+ if (!ssl)
1451
+ ossl_raise(eSSLError, NULL);
1452
+ RTYPEDDATA_DATA(self) = ssl;
1453
+
1454
+ SSL_set_ex_data(ssl, ossl_ssl_ex_ptr_idx, (void *)self);
1455
+ SSL_set_info_callback(ssl, ssl_info_cb);
1456
+ verify_cb = ossl_sslctx_get_verify_cb(v_ctx);
1457
+ SSL_set_ex_data(ssl, ossl_ssl_ex_vcb_idx, (void *)verify_cb);
1458
+
1459
+ rb_call_super(0, NULL);
1460
+
1461
+ return self;
1462
+ }
1463
+
1464
+ static VALUE
1465
+ ossl_ssl_setup(VALUE self)
1466
+ {
1467
+ VALUE io;
1468
+ SSL *ssl;
1469
+ rb_io_t *fptr;
1470
+
1471
+ GetSSL(self, ssl);
1472
+ if (ssl_started(ssl))
1473
+ return Qtrue;
1474
+
1475
+ io = ossl_ssl_get_io(self);
1476
+ GetOpenFile(io, fptr);
1477
+ rb_io_check_readable(fptr);
1478
+ rb_io_check_writable(fptr);
1479
+ SSL_set_fd(ssl, TO_SOCKET(FPTR_TO_FD(fptr)));
1480
+
1481
+ return Qtrue;
1482
+ }
1483
+
1484
+ #ifdef _WIN32
1485
+ #define ssl_get_error(ssl, ret) (errno = rb_w32_map_errno(WSAGetLastError()), SSL_get_error((ssl), (ret)))
1486
+ #else
1487
+ #define ssl_get_error(ssl, ret) SSL_get_error((ssl), (ret))
1488
+ #endif
1489
+
1490
+ static void
1491
+ write_would_block(int nonblock)
1492
+ {
1493
+ if (nonblock) {
1494
+ VALUE exc = ossl_exc_new(eSSLErrorWaitWritable, "write would block");
1495
+ rb_exc_raise(exc);
1496
+ }
1497
+ }
1498
+
1499
+ static void
1500
+ read_would_block(int nonblock)
1501
+ {
1502
+ if (nonblock) {
1503
+ VALUE exc = ossl_exc_new(eSSLErrorWaitReadable, "read would block");
1504
+ rb_exc_raise(exc);
1505
+ }
1506
+ }
1507
+
1508
+ static int
1509
+ no_exception_p(VALUE opts)
1510
+ {
1511
+ if (RB_TYPE_P(opts, T_HASH) &&
1512
+ rb_hash_lookup2(opts, sym_exception, Qundef) == Qfalse)
1513
+ return 1;
1514
+ return 0;
1515
+ }
1516
+
1517
+ static VALUE
1518
+ ossl_start_ssl(VALUE self, int (*func)(), const char *funcname, VALUE opts)
1519
+ {
1520
+ SSL *ssl;
1521
+ rb_io_t *fptr;
1522
+ int ret, ret2;
1523
+ VALUE cb_state;
1524
+ int nonblock = opts != Qfalse;
1525
+
1526
+ rb_ivar_set(self, ID_callback_state, Qnil);
1527
+
1528
+ GetSSL(self, ssl);
1529
+
1530
+ GetOpenFile(ossl_ssl_get_io(self), fptr);
1531
+ for(;;){
1532
+ ret = func(ssl);
1533
+
1534
+ cb_state = rb_ivar_get(self, ID_callback_state);
1535
+ if (!NIL_P(cb_state)) {
1536
+ /* must cleanup OpenSSL error stack before re-raising */
1537
+ ossl_clear_error();
1538
+ rb_jump_tag(NUM2INT(cb_state));
1539
+ }
1540
+
1541
+ if (ret > 0)
1542
+ break;
1543
+
1544
+ switch((ret2 = ssl_get_error(ssl, ret))){
1545
+ case SSL_ERROR_WANT_WRITE:
1546
+ if (no_exception_p(opts)) { return sym_wait_writable; }
1547
+ write_would_block(nonblock);
1548
+ rb_io_wait_writable(FPTR_TO_FD(fptr));
1549
+ continue;
1550
+ case SSL_ERROR_WANT_READ:
1551
+ if (no_exception_p(opts)) { return sym_wait_readable; }
1552
+ read_would_block(nonblock);
1553
+ rb_io_wait_readable(FPTR_TO_FD(fptr));
1554
+ continue;
1555
+ case SSL_ERROR_SYSCALL:
1556
+ if (errno) rb_sys_fail(funcname);
1557
+ ossl_raise(eSSLError, "%s SYSCALL returned=%d errno=%d state=%s", funcname, ret2, errno, SSL_state_string_long(ssl));
1558
+ default:
1559
+ ossl_raise(eSSLError, "%s returned=%d errno=%d state=%s", funcname, ret2, errno, SSL_state_string_long(ssl));
1560
+ }
1561
+ }
1562
+
1563
+ return self;
1564
+ }
1565
+
1566
+ /*
1567
+ * call-seq:
1568
+ * ssl.connect => self
1569
+ *
1570
+ * Initiates an SSL/TLS handshake with a server. The handshake may be started
1571
+ * after unencrypted data has been sent over the socket.
1572
+ */
1573
+ static VALUE
1574
+ ossl_ssl_connect(VALUE self)
1575
+ {
1576
+ ossl_ssl_setup(self);
1577
+
1578
+ return ossl_start_ssl(self, SSL_connect, "SSL_connect", Qfalse);
1579
+ }
1580
+
1581
+ /*
1582
+ * call-seq:
1583
+ * ssl.connect_nonblock([options]) => self
1584
+ *
1585
+ * Initiates the SSL/TLS handshake as a client in non-blocking manner.
1586
+ *
1587
+ * # emulates blocking connect
1588
+ * begin
1589
+ * ssl.connect_nonblock
1590
+ * rescue IO::WaitReadable
1591
+ * IO.select([s2])
1592
+ * retry
1593
+ * rescue IO::WaitWritable
1594
+ * IO.select(nil, [s2])
1595
+ * retry
1596
+ * end
1597
+ *
1598
+ * By specifying `exception: false`, the options hash allows you to indicate
1599
+ * that connect_nonblock should not raise an IO::WaitReadable or
1600
+ * IO::WaitWritable exception, but return the symbol :wait_readable or
1601
+ * :wait_writable instead.
1602
+ */
1603
+ static VALUE
1604
+ ossl_ssl_connect_nonblock(int argc, VALUE *argv, VALUE self)
1605
+ {
1606
+ VALUE opts;
1607
+ rb_scan_args(argc, argv, "0:", &opts);
1608
+
1609
+ ossl_ssl_setup(self);
1610
+
1611
+ return ossl_start_ssl(self, SSL_connect, "SSL_connect", opts);
1612
+ }
1613
+
1614
+ /*
1615
+ * call-seq:
1616
+ * ssl.accept => self
1617
+ *
1618
+ * Waits for a SSL/TLS client to initiate a handshake. The handshake may be
1619
+ * started after unencrypted data has been sent over the socket.
1620
+ */
1621
+ static VALUE
1622
+ ossl_ssl_accept(VALUE self)
1623
+ {
1624
+ ossl_ssl_setup(self);
1625
+
1626
+ return ossl_start_ssl(self, SSL_accept, "SSL_accept", Qfalse);
1627
+ }
1628
+
1629
+ /*
1630
+ * call-seq:
1631
+ * ssl.accept_nonblock([options]) => self
1632
+ *
1633
+ * Initiates the SSL/TLS handshake as a server in non-blocking manner.
1634
+ *
1635
+ * # emulates blocking accept
1636
+ * begin
1637
+ * ssl.accept_nonblock
1638
+ * rescue IO::WaitReadable
1639
+ * IO.select([s2])
1640
+ * retry
1641
+ * rescue IO::WaitWritable
1642
+ * IO.select(nil, [s2])
1643
+ * retry
1644
+ * end
1645
+ *
1646
+ * By specifying `exception: false`, the options hash allows you to indicate
1647
+ * that accept_nonblock should not raise an IO::WaitReadable or
1648
+ * IO::WaitWritable exception, but return the symbol :wait_readable or
1649
+ * :wait_writable instead.
1650
+ */
1651
+ static VALUE
1652
+ ossl_ssl_accept_nonblock(int argc, VALUE *argv, VALUE self)
1653
+ {
1654
+ VALUE opts;
1655
+
1656
+ rb_scan_args(argc, argv, "0:", &opts);
1657
+ ossl_ssl_setup(self);
1658
+
1659
+ return ossl_start_ssl(self, SSL_accept, "SSL_accept", opts);
1660
+ }
1661
+
1662
+ static VALUE
1663
+ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
1664
+ {
1665
+ SSL *ssl;
1666
+ int ilen, nread = 0;
1667
+ VALUE len, str;
1668
+ rb_io_t *fptr;
1669
+ VALUE opts = Qnil;
1670
+
1671
+ if (nonblock) {
1672
+ rb_scan_args(argc, argv, "11:", &len, &str, &opts);
1673
+ } else {
1674
+ rb_scan_args(argc, argv, "11", &len, &str);
1675
+ }
1676
+
1677
+ ilen = NUM2INT(len);
1678
+ if(NIL_P(str)) str = rb_str_new(0, ilen);
1679
+ else{
1680
+ StringValue(str);
1681
+ rb_str_modify(str);
1682
+ rb_str_resize(str, ilen);
1683
+ }
1684
+ if(ilen == 0) return str;
1685
+
1686
+ GetSSL(self, ssl);
1687
+ GetOpenFile(ossl_ssl_get_io(self), fptr);
1688
+ if (ssl_started(ssl)) {
1689
+ if(!nonblock && SSL_pending(ssl) <= 0)
1690
+ rb_thread_wait_fd(FPTR_TO_FD(fptr));
1691
+ for (;;){
1692
+ nread = SSL_read(ssl, RSTRING_PTR(str), RSTRING_LENINT(str));
1693
+ switch(ssl_get_error(ssl, nread)){
1694
+ case SSL_ERROR_NONE:
1695
+ goto end;
1696
+ case SSL_ERROR_ZERO_RETURN:
1697
+ if (no_exception_p(opts)) { return Qnil; }
1698
+ rb_eof_error();
1699
+ case SSL_ERROR_WANT_WRITE:
1700
+ if (no_exception_p(opts)) { return sym_wait_writable; }
1701
+ write_would_block(nonblock);
1702
+ rb_io_wait_writable(FPTR_TO_FD(fptr));
1703
+ continue;
1704
+ case SSL_ERROR_WANT_READ:
1705
+ if (no_exception_p(opts)) { return sym_wait_readable; }
1706
+ read_would_block(nonblock);
1707
+ rb_io_wait_readable(FPTR_TO_FD(fptr));
1708
+ continue;
1709
+ case SSL_ERROR_SYSCALL:
1710
+ if(ERR_peek_error() == 0 && nread == 0) {
1711
+ if (no_exception_p(opts)) { return Qnil; }
1712
+ rb_eof_error();
1713
+ }
1714
+ rb_sys_fail(0);
1715
+ default:
1716
+ ossl_raise(eSSLError, "SSL_read");
1717
+ }
1718
+ }
1719
+ }
1720
+ else {
1721
+ ID meth = nonblock ? rb_intern("read_nonblock") : rb_intern("sysread");
1722
+ rb_warning("SSL session is not started yet.");
1723
+ if (nonblock) {
1724
+ return rb_funcall(ossl_ssl_get_io(self), meth, 3, len, str, opts);
1725
+ } else {
1726
+ return rb_funcall(ossl_ssl_get_io(self), meth, 2, len, str);
1727
+ }
1728
+ }
1729
+
1730
+ end:
1731
+ rb_str_set_len(str, nread);
1732
+ OBJ_TAINT(str);
1733
+
1734
+ return str;
1735
+ }
1736
+
1737
+ /*
1738
+ * call-seq:
1739
+ * ssl.sysread(length) => string
1740
+ * ssl.sysread(length, buffer) => buffer
1741
+ *
1742
+ * Reads +length+ bytes from the SSL connection. If a pre-allocated +buffer+
1743
+ * is provided the data will be written into it.
1744
+ */
1745
+ static VALUE
1746
+ ossl_ssl_read(int argc, VALUE *argv, VALUE self)
1747
+ {
1748
+ return ossl_ssl_read_internal(argc, argv, self, 0);
1749
+ }
1750
+
1751
+ /*
1752
+ * call-seq:
1753
+ * ssl.sysread_nonblock(length) => string
1754
+ * ssl.sysread_nonblock(length, buffer) => buffer
1755
+ * ssl.sysread_nonblock(length[, buffer [, opts]) => buffer
1756
+ *
1757
+ * A non-blocking version of #sysread. Raises an SSLError if reading would
1758
+ * block. If "exception: false" is passed, this method returns a symbol of
1759
+ * :wait_readable, :wait_writable, or nil, rather than raising an exception.
1760
+ *
1761
+ * Reads +length+ bytes from the SSL connection. If a pre-allocated +buffer+
1762
+ * is provided the data will be written into it.
1763
+ */
1764
+ static VALUE
1765
+ ossl_ssl_read_nonblock(int argc, VALUE *argv, VALUE self)
1766
+ {
1767
+ return ossl_ssl_read_internal(argc, argv, self, 1);
1768
+ }
1769
+
1770
+ static VALUE
1771
+ ossl_ssl_write_internal(VALUE self, VALUE str, VALUE opts)
1772
+ {
1773
+ SSL *ssl;
1774
+ int nwrite = 0;
1775
+ rb_io_t *fptr;
1776
+ int nonblock = opts != Qfalse;
1777
+
1778
+ StringValue(str);
1779
+ GetSSL(self, ssl);
1780
+ GetOpenFile(ossl_ssl_get_io(self), fptr);
1781
+
1782
+ if (ssl_started(ssl)) {
1783
+ for (;;){
1784
+ int num = RSTRING_LENINT(str);
1785
+
1786
+ /* SSL_write(3ssl) manpage states num == 0 is undefined */
1787
+ if (num == 0)
1788
+ goto end;
1789
+
1790
+ nwrite = SSL_write(ssl, RSTRING_PTR(str), num);
1791
+ switch(ssl_get_error(ssl, nwrite)){
1792
+ case SSL_ERROR_NONE:
1793
+ goto end;
1794
+ case SSL_ERROR_WANT_WRITE:
1795
+ if (no_exception_p(opts)) { return sym_wait_writable; }
1796
+ write_would_block(nonblock);
1797
+ rb_io_wait_writable(FPTR_TO_FD(fptr));
1798
+ continue;
1799
+ case SSL_ERROR_WANT_READ:
1800
+ if (no_exception_p(opts)) { return sym_wait_readable; }
1801
+ read_would_block(nonblock);
1802
+ rb_io_wait_readable(FPTR_TO_FD(fptr));
1803
+ continue;
1804
+ case SSL_ERROR_SYSCALL:
1805
+ if (errno) rb_sys_fail(0);
1806
+ default:
1807
+ ossl_raise(eSSLError, "SSL_write");
1808
+ }
1809
+ }
1810
+ }
1811
+ else {
1812
+ ID id_syswrite = rb_intern("syswrite");
1813
+ rb_warning("SSL session is not started yet.");
1814
+ return rb_funcall(ossl_ssl_get_io(self), id_syswrite, 1, str);
1815
+ }
1816
+
1817
+ end:
1818
+ return INT2NUM(nwrite);
1819
+ }
1820
+
1821
+ /*
1822
+ * call-seq:
1823
+ * ssl.syswrite(string) => Integer
1824
+ *
1825
+ * Writes +string+ to the SSL connection.
1826
+ */
1827
+ static VALUE
1828
+ ossl_ssl_write(VALUE self, VALUE str)
1829
+ {
1830
+ return ossl_ssl_write_internal(self, str, Qfalse);
1831
+ }
1832
+
1833
+ /*
1834
+ * call-seq:
1835
+ * ssl.syswrite_nonblock(string) => Integer
1836
+ *
1837
+ * Writes +string+ to the SSL connection in a non-blocking manner. Raises an
1838
+ * SSLError if writing would block.
1839
+ */
1840
+ static VALUE
1841
+ ossl_ssl_write_nonblock(int argc, VALUE *argv, VALUE self)
1842
+ {
1843
+ VALUE str, opts;
1844
+
1845
+ rb_scan_args(argc, argv, "1:", &str, &opts);
1846
+
1847
+ return ossl_ssl_write_internal(self, str, opts);
1848
+ }
1849
+
1850
+ /*
1851
+ * call-seq:
1852
+ * ssl.stop => nil
1853
+ *
1854
+ * Sends "close notify" to the peer and tries to shut down the SSL connection
1855
+ * gracefully.
1856
+ */
1857
+ static VALUE
1858
+ ossl_ssl_stop(VALUE self)
1859
+ {
1860
+ SSL *ssl;
1861
+
1862
+ GetSSL(self, ssl);
1863
+
1864
+ ossl_ssl_shutdown(ssl);
1865
+
1866
+ return Qnil;
1867
+ }
1868
+
1869
+ /*
1870
+ * call-seq:
1871
+ * ssl.cert => cert or nil
1872
+ *
1873
+ * The X509 certificate for this socket endpoint.
1874
+ */
1875
+ static VALUE
1876
+ ossl_ssl_get_cert(VALUE self)
1877
+ {
1878
+ SSL *ssl;
1879
+ X509 *cert = NULL;
1880
+
1881
+ GetSSL(self, ssl);
1882
+
1883
+ /*
1884
+ * Is this OpenSSL bug? Should add a ref?
1885
+ * TODO: Ask for.
1886
+ */
1887
+ cert = SSL_get_certificate(ssl); /* NO DUPs => DON'T FREE. */
1888
+
1889
+ if (!cert) {
1890
+ return Qnil;
1891
+ }
1892
+ return ossl_x509_new(cert);
1893
+ }
1894
+
1895
+ /*
1896
+ * call-seq:
1897
+ * ssl.peer_cert => cert or nil
1898
+ *
1899
+ * The X509 certificate for this socket's peer.
1900
+ */
1901
+ static VALUE
1902
+ ossl_ssl_get_peer_cert(VALUE self)
1903
+ {
1904
+ SSL *ssl;
1905
+ X509 *cert = NULL;
1906
+ VALUE obj;
1907
+
1908
+ GetSSL(self, ssl);
1909
+
1910
+ cert = SSL_get_peer_certificate(ssl); /* Adds a ref => Safe to FREE. */
1911
+
1912
+ if (!cert) {
1913
+ return Qnil;
1914
+ }
1915
+ obj = ossl_x509_new(cert);
1916
+ X509_free(cert);
1917
+
1918
+ return obj;
1919
+ }
1920
+
1921
+ /*
1922
+ * call-seq:
1923
+ * ssl.peer_cert_chain => [cert, ...] or nil
1924
+ *
1925
+ * The X509 certificate chain for this socket's peer.
1926
+ */
1927
+ static VALUE
1928
+ ossl_ssl_get_peer_cert_chain(VALUE self)
1929
+ {
1930
+ SSL *ssl;
1931
+ STACK_OF(X509) *chain;
1932
+ X509 *cert;
1933
+ VALUE ary;
1934
+ int i, num;
1935
+
1936
+ GetSSL(self, ssl);
1937
+
1938
+ chain = SSL_get_peer_cert_chain(ssl);
1939
+ if(!chain) return Qnil;
1940
+ num = sk_X509_num(chain);
1941
+ ary = rb_ary_new2(num);
1942
+ for (i = 0; i < num; i++){
1943
+ cert = sk_X509_value(chain, i);
1944
+ rb_ary_push(ary, ossl_x509_new(cert));
1945
+ }
1946
+
1947
+ return ary;
1948
+ }
1949
+
1950
+ /*
1951
+ * call-seq:
1952
+ * ssl.ssl_version => String
1953
+ *
1954
+ * Returns a String representing the SSL/TLS version that was negotiated
1955
+ * for the connection, for example "TLSv1.2".
1956
+ */
1957
+ static VALUE
1958
+ ossl_ssl_get_version(VALUE self)
1959
+ {
1960
+ SSL *ssl;
1961
+
1962
+ GetSSL(self, ssl);
1963
+
1964
+ return rb_str_new2(SSL_get_version(ssl));
1965
+ }
1966
+
1967
+ /*
1968
+ * call-seq:
1969
+ * ssl.cipher => [name, version, bits, alg_bits]
1970
+ *
1971
+ * The cipher being used for the current connection
1972
+ */
1973
+ static VALUE
1974
+ ossl_ssl_get_cipher(VALUE self)
1975
+ {
1976
+ SSL *ssl;
1977
+ SSL_CIPHER *cipher;
1978
+
1979
+ GetSSL(self, ssl);
1980
+
1981
+ cipher = (SSL_CIPHER *)SSL_get_current_cipher(ssl);
1982
+
1983
+ return ossl_ssl_cipher_to_ary(cipher);
1984
+ }
1985
+
1986
+ /*
1987
+ * call-seq:
1988
+ * ssl.state => string
1989
+ *
1990
+ * A description of the current connection state. This is for diagnostic
1991
+ * purposes only.
1992
+ */
1993
+ static VALUE
1994
+ ossl_ssl_get_state(VALUE self)
1995
+ {
1996
+ SSL *ssl;
1997
+ VALUE ret;
1998
+
1999
+ GetSSL(self, ssl);
2000
+
2001
+ ret = rb_str_new2(SSL_state_string(ssl));
2002
+ if (ruby_verbose) {
2003
+ rb_str_cat2(ret, ": ");
2004
+ rb_str_cat2(ret, SSL_state_string_long(ssl));
2005
+ }
2006
+ return ret;
2007
+ }
2008
+
2009
+ /*
2010
+ * call-seq:
2011
+ * ssl.pending => Integer
2012
+ *
2013
+ * The number of bytes that are immediately available for reading.
2014
+ */
2015
+ static VALUE
2016
+ ossl_ssl_pending(VALUE self)
2017
+ {
2018
+ SSL *ssl;
2019
+
2020
+ GetSSL(self, ssl);
2021
+
2022
+ return INT2NUM(SSL_pending(ssl));
2023
+ }
2024
+
2025
+ /*
2026
+ * call-seq:
2027
+ * ssl.session_reused? -> true | false
2028
+ *
2029
+ * Returns true if a reused session was negotiated during the handshake.
2030
+ */
2031
+ static VALUE
2032
+ ossl_ssl_session_reused(VALUE self)
2033
+ {
2034
+ SSL *ssl;
2035
+
2036
+ GetSSL(self, ssl);
2037
+
2038
+ return SSL_session_reused(ssl) ? Qtrue : Qfalse;
2039
+ }
2040
+
2041
+ /*
2042
+ * call-seq:
2043
+ * ssl.session = session -> session
2044
+ *
2045
+ * Sets the Session to be used when the connection is established.
2046
+ */
2047
+ static VALUE
2048
+ ossl_ssl_set_session(VALUE self, VALUE arg1)
2049
+ {
2050
+ SSL *ssl;
2051
+ SSL_SESSION *sess;
2052
+
2053
+ GetSSL(self, ssl);
2054
+ SafeGetSSLSession(arg1, sess);
2055
+
2056
+ if (SSL_set_session(ssl, sess) != 1)
2057
+ ossl_raise(eSSLError, "SSL_set_session");
2058
+
2059
+ return arg1;
2060
+ }
2061
+
2062
+ #ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME
2063
+ /*
2064
+ * call-seq:
2065
+ * ssl.hostname = hostname -> hostname
2066
+ *
2067
+ * Sets the server hostname used for SNI. This needs to be set before
2068
+ * SSLSocket#connect.
2069
+ */
2070
+ static VALUE
2071
+ ossl_ssl_set_hostname(VALUE self, VALUE arg)
2072
+ {
2073
+ SSL *ssl;
2074
+ char *hostname = NULL;
2075
+
2076
+ GetSSL(self, ssl);
2077
+
2078
+ if (!NIL_P(arg))
2079
+ hostname = StringValueCStr(arg);
2080
+
2081
+ if (!SSL_set_tlsext_host_name(ssl, hostname))
2082
+ ossl_raise(eSSLError, NULL);
2083
+
2084
+ /* for SSLSocket#hostname */
2085
+ ossl_ssl_set_hostname_v(self, arg);
2086
+
2087
+ return arg;
2088
+ }
2089
+ #endif
2090
+
2091
+ /*
2092
+ * call-seq:
2093
+ * ssl.verify_result => Integer
2094
+ *
2095
+ * Returns the result of the peer certificates verification. See verify(1)
2096
+ * for error values and descriptions.
2097
+ *
2098
+ * If no peer certificate was presented X509_V_OK is returned.
2099
+ */
2100
+ static VALUE
2101
+ ossl_ssl_get_verify_result(VALUE self)
2102
+ {
2103
+ SSL *ssl;
2104
+
2105
+ GetSSL(self, ssl);
2106
+
2107
+ return INT2NUM(SSL_get_verify_result(ssl));
2108
+ }
2109
+
2110
+ /*
2111
+ * call-seq:
2112
+ * ssl.client_ca => [x509name, ...]
2113
+ *
2114
+ * Returns the list of client CAs. Please note that in contrast to
2115
+ * SSLContext#client_ca= no array of X509::Certificate is returned but
2116
+ * X509::Name instances of the CA's subject distinguished name.
2117
+ *
2118
+ * In server mode, returns the list set by SSLContext#client_ca=.
2119
+ * In client mode, returns the list of client CAs sent from the server.
2120
+ */
2121
+ static VALUE
2122
+ ossl_ssl_get_client_ca_list(VALUE self)
2123
+ {
2124
+ SSL *ssl;
2125
+ STACK_OF(X509_NAME) *ca;
2126
+
2127
+ GetSSL(self, ssl);
2128
+
2129
+ ca = SSL_get_client_CA_list(ssl);
2130
+ return ossl_x509name_sk2ary(ca);
2131
+ }
2132
+
2133
+ # ifdef HAVE_SSL_CTX_SET_NEXT_PROTO_SELECT_CB
2134
+ /*
2135
+ * call-seq:
2136
+ * ssl.npn_protocol => String | nil
2137
+ *
2138
+ * Returns the protocol string that was finally selected by the client
2139
+ * during the handshake.
2140
+ */
2141
+ static VALUE
2142
+ ossl_ssl_npn_protocol(VALUE self)
2143
+ {
2144
+ SSL *ssl;
2145
+ const unsigned char *out;
2146
+ unsigned int outlen;
2147
+
2148
+ GetSSL(self, ssl);
2149
+
2150
+ SSL_get0_next_proto_negotiated(ssl, &out, &outlen);
2151
+ if (!outlen)
2152
+ return Qnil;
2153
+ else
2154
+ return rb_str_new((const char *) out, outlen);
2155
+ }
2156
+ # endif
2157
+
2158
+ # ifdef HAVE_SSL_CTX_SET_ALPN_SELECT_CB
2159
+ /*
2160
+ * call-seq:
2161
+ * ssl.alpn_protocol => String | nil
2162
+ *
2163
+ * Returns the ALPN protocol string that was finally selected by the server
2164
+ * during the handshake.
2165
+ */
2166
+ static VALUE
2167
+ ossl_ssl_alpn_protocol(VALUE self)
2168
+ {
2169
+ SSL *ssl;
2170
+ const unsigned char *out;
2171
+ unsigned int outlen;
2172
+
2173
+ GetSSL(self, ssl);
2174
+
2175
+ SSL_get0_alpn_selected(ssl, &out, &outlen);
2176
+ if (!outlen)
2177
+ return Qnil;
2178
+ else
2179
+ return rb_str_new((const char *) out, outlen);
2180
+ }
2181
+ # endif
2182
+
2183
+ # ifdef HAVE_SSL_GET_SERVER_TMP_KEY
2184
+ /*
2185
+ * call-seq:
2186
+ * ssl.tmp_key => PKey or nil
2187
+ *
2188
+ * Returns the ephemeral key used in case of forward secrecy cipher.
2189
+ */
2190
+ static VALUE
2191
+ ossl_ssl_tmp_key(VALUE self)
2192
+ {
2193
+ SSL *ssl;
2194
+ EVP_PKEY *key;
2195
+
2196
+ GetSSL(self, ssl);
2197
+ if (!SSL_get_server_tmp_key(ssl, &key))
2198
+ return Qnil;
2199
+ return ossl_pkey_new(key);
2200
+ }
2201
+ # endif /* defined(HAVE_SSL_GET_SERVER_TMP_KEY) */
2202
+ #endif /* !defined(OPENSSL_NO_SOCK) */
2203
+
2204
+ void
2205
+ Init_ossl_ssl(void)
2206
+ {
2207
+ int i;
2208
+ VALUE ary;
2209
+
2210
+ #if 0
2211
+ mOSSL = rb_define_module("OpenSSL");
2212
+ eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
2213
+ rb_mWaitReadable = rb_define_module_under(rb_cIO, "WaitReadable");
2214
+ rb_mWaitWritable = rb_define_module_under(rb_cIO, "WaitWritable");
2215
+ #endif
2216
+
2217
+ ID_callback_state = rb_intern("@callback_state");
2218
+
2219
+ ossl_ssl_ex_vcb_idx = SSL_get_ex_new_index(0,(void *)"ossl_ssl_ex_vcb_idx",0,0,0);
2220
+ ossl_ssl_ex_store_p = SSL_get_ex_new_index(0,(void *)"ossl_ssl_ex_store_p",0,0,0);
2221
+ ossl_ssl_ex_ptr_idx = SSL_get_ex_new_index(0,(void *)"ossl_ssl_ex_ptr_idx",0,0,0);
2222
+
2223
+ /* Document-module: OpenSSL::SSL
2224
+ *
2225
+ * Use SSLContext to set up the parameters for a TLS (former SSL)
2226
+ * connection. Both client and server TLS connections are supported,
2227
+ * SSLSocket and SSLServer may be used in conjunction with an instance
2228
+ * of SSLContext to set up connections.
2229
+ */
2230
+ mSSL = rb_define_module_under(mOSSL, "SSL");
2231
+
2232
+ /* Document-module: OpenSSL::ExtConfig
2233
+ *
2234
+ * This module contains configuration information about the SSL extension,
2235
+ * for example if socket support is enabled, or the host name TLS extension
2236
+ * is enabled. Constants in this module will always be defined, but contain
2237
+ * `true` or `false` values depending on the configuration of your OpenSSL
2238
+ * installation.
2239
+ */
2240
+ mSSLExtConfig = rb_define_module_under(mOSSL, "ExtConfig");
2241
+
2242
+ /* Document-class: OpenSSL::SSL::SSLError
2243
+ *
2244
+ * Generic error class raised by SSLSocket and SSLContext.
2245
+ */
2246
+ eSSLError = rb_define_class_under(mSSL, "SSLError", eOSSLError);
2247
+ eSSLErrorWaitReadable = rb_define_class_under(mSSL, "SSLErrorWaitReadable", eSSLError);
2248
+ rb_include_module(eSSLErrorWaitReadable, rb_mWaitReadable);
2249
+ eSSLErrorWaitWritable = rb_define_class_under(mSSL, "SSLErrorWaitWritable", eSSLError);
2250
+ rb_include_module(eSSLErrorWaitWritable, rb_mWaitWritable);
2251
+
2252
+ Init_ossl_ssl_session();
2253
+
2254
+ /* Document-class: OpenSSL::SSL::SSLContext
2255
+ *
2256
+ * An SSLContext is used to set various options regarding certificates,
2257
+ * algorithms, verification, session caching, etc. The SSLContext is
2258
+ * used to create an SSLSocket.
2259
+ *
2260
+ * All attributes must be set before creating an SSLSocket as the
2261
+ * SSLContext will be frozen afterward.
2262
+ */
2263
+ cSSLContext = rb_define_class_under(mSSL, "SSLContext", rb_cObject);
2264
+ rb_define_alloc_func(cSSLContext, ossl_sslctx_s_alloc);
2265
+ rb_undef_method(cSSLContext, "initialize_copy");
2266
+
2267
+ /*
2268
+ * Context certificate
2269
+ */
2270
+ rb_attr(cSSLContext, rb_intern("cert"), 1, 1, Qfalse);
2271
+
2272
+ /*
2273
+ * Context private key
2274
+ */
2275
+ rb_attr(cSSLContext, rb_intern("key"), 1, 1, Qfalse);
2276
+
2277
+ /*
2278
+ * A certificate or Array of certificates that will be sent to the client.
2279
+ */
2280
+ rb_attr(cSSLContext, rb_intern("client_ca"), 1, 1, Qfalse);
2281
+
2282
+ /*
2283
+ * The path to a file containing a PEM-format CA certificate
2284
+ */
2285
+ rb_attr(cSSLContext, rb_intern("ca_file"), 1, 1, Qfalse);
2286
+
2287
+ /*
2288
+ * The path to a directory containing CA certificates in PEM format.
2289
+ *
2290
+ * Files are looked up by subject's X509 name's hash value.
2291
+ */
2292
+ rb_attr(cSSLContext, rb_intern("ca_path"), 1, 1, Qfalse);
2293
+
2294
+ /*
2295
+ * Maximum session lifetime in seconds.
2296
+ */
2297
+ rb_attr(cSSLContext, rb_intern("timeout"), 1, 1, Qfalse);
2298
+
2299
+ /*
2300
+ * Session verification mode.
2301
+ *
2302
+ * Valid modes are VERIFY_NONE, VERIFY_PEER, VERIFY_CLIENT_ONCE,
2303
+ * VERIFY_FAIL_IF_NO_PEER_CERT and defined on OpenSSL::SSL
2304
+ *
2305
+ * The default mode is VERIFY_NONE, which does not perform any verification
2306
+ * at all.
2307
+ *
2308
+ * See SSL_CTX_set_verify(3) for details.
2309
+ */
2310
+ rb_attr(cSSLContext, rb_intern("verify_mode"), 1, 1, Qfalse);
2311
+
2312
+ /*
2313
+ * Number of CA certificates to walk when verifying a certificate chain.
2314
+ */
2315
+ rb_attr(cSSLContext, rb_intern("verify_depth"), 1, 1, Qfalse);
2316
+
2317
+ /*
2318
+ * A callback for additional certificate verification. The callback is
2319
+ * invoked for each certificate in the chain.
2320
+ *
2321
+ * The callback is invoked with two values. +preverify_ok+ indicates
2322
+ * indicates if the verification was passed (true) or not (false).
2323
+ * +store_context+ is an OpenSSL::X509::StoreContext containing the
2324
+ * context used for certificate verification.
2325
+ *
2326
+ * If the callback returns false, the chain verification is immediately
2327
+ * stopped and a bad_certificate alert is then sent.
2328
+ */
2329
+ rb_attr(cSSLContext, rb_intern("verify_callback"), 1, 1, Qfalse);
2330
+
2331
+ /*
2332
+ * Whether to check the server certificate is valid for the hostname.
2333
+ *
2334
+ * In order to make this work, verify_mode must be set to VERIFY_PEER and
2335
+ * the server hostname must be given by OpenSSL::SSL::SSLSocket#hostname=.
2336
+ */
2337
+ rb_attr(cSSLContext, rb_intern("verify_hostname"), 1, 1, Qfalse);
2338
+
2339
+ /*
2340
+ * An OpenSSL::X509::Store used for certificate verification.
2341
+ */
2342
+ rb_attr(cSSLContext, rb_intern("cert_store"), 1, 1, Qfalse);
2343
+
2344
+ /*
2345
+ * An Array of extra X509 certificates to be added to the certificate
2346
+ * chain.
2347
+ */
2348
+ rb_attr(cSSLContext, rb_intern("extra_chain_cert"), 1, 1, Qfalse);
2349
+
2350
+ /*
2351
+ * A callback invoked when a client certificate is requested by a server
2352
+ * and no certificate has been set.
2353
+ *
2354
+ * The callback is invoked with a Session and must return an Array
2355
+ * containing an OpenSSL::X509::Certificate and an OpenSSL::PKey. If any
2356
+ * other value is returned the handshake is suspended.
2357
+ */
2358
+ rb_attr(cSSLContext, rb_intern("client_cert_cb"), 1, 1, Qfalse);
2359
+
2360
+ #if !defined(OPENSSL_NO_EC) && defined(HAVE_SSL_CTX_SET_TMP_ECDH_CALLBACK)
2361
+ /*
2362
+ * A callback invoked when ECDH parameters are required.
2363
+ *
2364
+ * The callback is invoked with the Session for the key exchange, an
2365
+ * flag indicating the use of an export cipher and the keylength
2366
+ * required.
2367
+ *
2368
+ * The callback is deprecated. This does not work with recent versions of
2369
+ * OpenSSL. Use OpenSSL::SSL::SSLContext#ecdh_curves= instead.
2370
+ */
2371
+ rb_attr(cSSLContext, rb_intern("tmp_ecdh_callback"), 1, 1, Qfalse);
2372
+ #endif
2373
+
2374
+ /*
2375
+ * Sets the context in which a session can be reused. This allows
2376
+ * sessions for multiple applications to be distinguished, for example, by
2377
+ * name.
2378
+ */
2379
+ rb_attr(cSSLContext, rb_intern("session_id_context"), 1, 1, Qfalse);
2380
+
2381
+ /*
2382
+ * A callback invoked on a server when a session is proposed by the client
2383
+ * but the session could not be found in the server's internal cache.
2384
+ *
2385
+ * The callback is invoked with the SSLSocket and session id. The
2386
+ * callback may return a Session from an external cache.
2387
+ */
2388
+ rb_attr(cSSLContext, rb_intern("session_get_cb"), 1, 1, Qfalse);
2389
+
2390
+ /*
2391
+ * A callback invoked when a new session was negotiated.
2392
+ *
2393
+ * The callback is invoked with an SSLSocket. If false is returned the
2394
+ * session will be removed from the internal cache.
2395
+ */
2396
+ rb_attr(cSSLContext, rb_intern("session_new_cb"), 1, 1, Qfalse);
2397
+
2398
+ /*
2399
+ * A callback invoked when a session is removed from the internal cache.
2400
+ *
2401
+ * The callback is invoked with an SSLContext and a Session.
2402
+ */
2403
+ rb_attr(cSSLContext, rb_intern("session_remove_cb"), 1, 1, Qfalse);
2404
+
2405
+ #ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME
2406
+ rb_define_const(mSSLExtConfig, "HAVE_TLSEXT_HOST_NAME", Qtrue);
2407
+ #else
2408
+ rb_define_const(mSSLExtConfig, "HAVE_TLSEXT_HOST_NAME", Qfalse);
2409
+ #endif
2410
+
2411
+ #ifdef TLS_DH_anon_WITH_AES_256_GCM_SHA384
2412
+ rb_define_const(mSSLExtConfig, "TLS_DH_anon_WITH_AES_256_GCM_SHA384", Qtrue);
2413
+ #else
2414
+ rb_define_const(mSSLExtConfig, "TLS_DH_anon_WITH_AES_256_GCM_SHA384", Qfalse);
2415
+ #endif
2416
+
2417
+ /*
2418
+ * A callback invoked whenever a new handshake is initiated. May be used
2419
+ * to disable renegotiation entirely.
2420
+ *
2421
+ * The callback is invoked with the active SSLSocket. The callback's
2422
+ * return value is irrelevant, normal return indicates "approval" of the
2423
+ * renegotiation and will continue the process. To forbid renegotiation
2424
+ * and to cancel the process, an Error may be raised within the callback.
2425
+ *
2426
+ * === Disable client renegotiation
2427
+ *
2428
+ * When running a server, it is often desirable to disable client
2429
+ * renegotiation entirely. You may use a callback as follows to implement
2430
+ * this feature:
2431
+ *
2432
+ * num_handshakes = 0
2433
+ * ctx.renegotiation_cb = lambda do |ssl|
2434
+ * num_handshakes += 1
2435
+ * raise RuntimeError.new("Client renegotiation disabled") if num_handshakes > 1
2436
+ * end
2437
+ */
2438
+ rb_attr(cSSLContext, rb_intern("renegotiation_cb"), 1, 1, Qfalse);
2439
+ #ifdef HAVE_SSL_CTX_SET_NEXT_PROTO_SELECT_CB
2440
+ /*
2441
+ * An Enumerable of Strings. Each String represents a protocol to be
2442
+ * advertised as the list of supported protocols for Next Protocol
2443
+ * Negotiation. Supported in OpenSSL 1.0.1 and higher. Has no effect
2444
+ * on the client side. If not set explicitly, the NPN extension will
2445
+ * not be sent by the server in the handshake.
2446
+ *
2447
+ * === Example
2448
+ *
2449
+ * ctx.npn_protocols = ["http/1.1", "spdy/2"]
2450
+ */
2451
+ rb_attr(cSSLContext, rb_intern("npn_protocols"), 1, 1, Qfalse);
2452
+ /*
2453
+ * A callback invoked on the client side when the client needs to select
2454
+ * a protocol from the list sent by the server. Supported in OpenSSL 1.0.1
2455
+ * and higher. The client MUST select a protocol of those advertised by
2456
+ * the server. If none is acceptable, raising an error in the callback
2457
+ * will cause the handshake to fail. Not setting this callback explicitly
2458
+ * means not supporting the NPN extension on the client - any protocols
2459
+ * advertised by the server will be ignored.
2460
+ *
2461
+ * === Example
2462
+ *
2463
+ * ctx.npn_select_cb = lambda do |protocols|
2464
+ * # inspect the protocols and select one
2465
+ * protocols.first
2466
+ * end
2467
+ */
2468
+ rb_attr(cSSLContext, rb_intern("npn_select_cb"), 1, 1, Qfalse);
2469
+ #endif
2470
+
2471
+ #ifdef HAVE_SSL_CTX_SET_ALPN_SELECT_CB
2472
+ /*
2473
+ * An Enumerable of Strings. Each String represents a protocol to be
2474
+ * advertised as the list of supported protocols for Application-Layer
2475
+ * Protocol Negotiation. Supported in OpenSSL 1.0.2 and higher. Has no
2476
+ * effect on the server side. If not set explicitly, the ALPN extension will
2477
+ * not be included in the handshake.
2478
+ *
2479
+ * === Example
2480
+ *
2481
+ * ctx.alpn_protocols = ["http/1.1", "spdy/2", "h2"]
2482
+ */
2483
+ rb_attr(cSSLContext, rb_intern("alpn_protocols"), 1, 1, Qfalse);
2484
+ /*
2485
+ * A callback invoked on the server side when the server needs to select
2486
+ * a protocol from the list sent by the client. Supported in OpenSSL 1.0.2
2487
+ * and higher. The callback must return a protocol of those advertised by
2488
+ * the client. If none is acceptable, raising an error in the callback
2489
+ * will cause the handshake to fail. Not setting this callback explicitly
2490
+ * means not supporting the ALPN extension on the server - any protocols
2491
+ * advertised by the client will be ignored.
2492
+ *
2493
+ * === Example
2494
+ *
2495
+ * ctx.alpn_select_cb = lambda do |protocols|
2496
+ * # inspect the protocols and select one
2497
+ * protocols.first
2498
+ * end
2499
+ */
2500
+ rb_attr(cSSLContext, rb_intern("alpn_select_cb"), 1, 1, Qfalse);
2501
+ #endif
2502
+
2503
+ rb_define_alias(cSSLContext, "ssl_timeout", "timeout");
2504
+ rb_define_alias(cSSLContext, "ssl_timeout=", "timeout=");
2505
+ rb_define_method(cSSLContext, "ssl_version=", ossl_sslctx_set_ssl_version, 1);
2506
+ rb_define_method(cSSLContext, "ciphers", ossl_sslctx_get_ciphers, 0);
2507
+ rb_define_method(cSSLContext, "ciphers=", ossl_sslctx_set_ciphers, 1);
2508
+ rb_define_method(cSSLContext, "ecdh_curves=", ossl_sslctx_set_ecdh_curves, 1);
2509
+ rb_define_method(cSSLContext, "security_level", ossl_sslctx_get_security_level, 0);
2510
+ rb_define_method(cSSLContext, "security_level=", ossl_sslctx_set_security_level, 1);
2511
+
2512
+ rb_define_method(cSSLContext, "setup", ossl_sslctx_setup, 0);
2513
+
2514
+ /*
2515
+ * No session caching for client or server
2516
+ */
2517
+ rb_define_const(cSSLContext, "SESSION_CACHE_OFF", LONG2NUM(SSL_SESS_CACHE_OFF));
2518
+
2519
+ /*
2520
+ * Client sessions are added to the session cache
2521
+ */
2522
+ rb_define_const(cSSLContext, "SESSION_CACHE_CLIENT", LONG2NUM(SSL_SESS_CACHE_CLIENT)); /* doesn't actually do anything in 0.9.8e */
2523
+
2524
+ /*
2525
+ * Server sessions are added to the session cache
2526
+ */
2527
+ rb_define_const(cSSLContext, "SESSION_CACHE_SERVER", LONG2NUM(SSL_SESS_CACHE_SERVER));
2528
+
2529
+ /*
2530
+ * Both client and server sessions are added to the session cache
2531
+ */
2532
+ rb_define_const(cSSLContext, "SESSION_CACHE_BOTH", LONG2NUM(SSL_SESS_CACHE_BOTH)); /* no different than CACHE_SERVER in 0.9.8e */
2533
+
2534
+ /*
2535
+ * Normally the session cache is checked for expired sessions every 255
2536
+ * connections. Since this may lead to a delay that cannot be controlled,
2537
+ * the automatic flushing may be disabled and #flush_sessions can be
2538
+ * called explicitly.
2539
+ */
2540
+ rb_define_const(cSSLContext, "SESSION_CACHE_NO_AUTO_CLEAR", LONG2NUM(SSL_SESS_CACHE_NO_AUTO_CLEAR));
2541
+
2542
+ /*
2543
+ * Always perform external lookups of sessions even if they are in the
2544
+ * internal cache.
2545
+ *
2546
+ * This flag has no effect on clients
2547
+ */
2548
+ rb_define_const(cSSLContext, "SESSION_CACHE_NO_INTERNAL_LOOKUP", LONG2NUM(SSL_SESS_CACHE_NO_INTERNAL_LOOKUP));
2549
+
2550
+ /*
2551
+ * Never automatically store sessions in the internal store.
2552
+ */
2553
+ rb_define_const(cSSLContext, "SESSION_CACHE_NO_INTERNAL_STORE", LONG2NUM(SSL_SESS_CACHE_NO_INTERNAL_STORE));
2554
+
2555
+ /*
2556
+ * Enables both SESSION_CACHE_NO_INTERNAL_LOOKUP and
2557
+ * SESSION_CACHE_NO_INTERNAL_STORE.
2558
+ */
2559
+ rb_define_const(cSSLContext, "SESSION_CACHE_NO_INTERNAL", LONG2NUM(SSL_SESS_CACHE_NO_INTERNAL));
2560
+
2561
+ rb_define_method(cSSLContext, "session_add", ossl_sslctx_session_add, 1);
2562
+ rb_define_method(cSSLContext, "session_remove", ossl_sslctx_session_remove, 1);
2563
+ rb_define_method(cSSLContext, "session_cache_mode", ossl_sslctx_get_session_cache_mode, 0);
2564
+ rb_define_method(cSSLContext, "session_cache_mode=", ossl_sslctx_set_session_cache_mode, 1);
2565
+ rb_define_method(cSSLContext, "session_cache_size", ossl_sslctx_get_session_cache_size, 0);
2566
+ rb_define_method(cSSLContext, "session_cache_size=", ossl_sslctx_set_session_cache_size, 1);
2567
+ rb_define_method(cSSLContext, "session_cache_stats", ossl_sslctx_get_session_cache_stats, 0);
2568
+ rb_define_method(cSSLContext, "flush_sessions", ossl_sslctx_flush_sessions, -1);
2569
+ rb_define_method(cSSLContext, "options", ossl_sslctx_get_options, 0);
2570
+ rb_define_method(cSSLContext, "options=", ossl_sslctx_set_options, 1);
2571
+
2572
+ ary = rb_ary_new2(numberof(ossl_ssl_method_tab));
2573
+ for (i = 0; i < numberof(ossl_ssl_method_tab); i++) {
2574
+ rb_ary_push(ary, ID2SYM(rb_intern(ossl_ssl_method_tab[i].name)));
2575
+ }
2576
+ rb_obj_freeze(ary);
2577
+ /* The list of available SSL/TLS methods */
2578
+ rb_define_const(cSSLContext, "METHODS", ary);
2579
+
2580
+ /*
2581
+ * Document-class: OpenSSL::SSL::SSLSocket
2582
+ */
2583
+ cSSLSocket = rb_define_class_under(mSSL, "SSLSocket", rb_cObject);
2584
+ #ifdef OPENSSL_NO_SOCK
2585
+ rb_define_const(mSSLExtConfig, "OPENSSL_NO_SOCK", Qtrue);
2586
+ rb_define_method(cSSLSocket, "initialize", rb_f_notimplement, -1);
2587
+ #else
2588
+ rb_define_const(mSSLExtConfig, "OPENSSL_NO_SOCK", Qfalse);
2589
+ rb_define_alloc_func(cSSLSocket, ossl_ssl_s_alloc);
2590
+ rb_define_method(cSSLSocket, "initialize", ossl_ssl_initialize, -1);
2591
+ rb_undef_method(cSSLSocket, "initialize_copy");
2592
+ rb_define_method(cSSLSocket, "connect", ossl_ssl_connect, 0);
2593
+ rb_define_method(cSSLSocket, "connect_nonblock", ossl_ssl_connect_nonblock, -1);
2594
+ rb_define_method(cSSLSocket, "accept", ossl_ssl_accept, 0);
2595
+ rb_define_method(cSSLSocket, "accept_nonblock", ossl_ssl_accept_nonblock, -1);
2596
+ rb_define_method(cSSLSocket, "sysread", ossl_ssl_read, -1);
2597
+ rb_define_private_method(cSSLSocket, "sysread_nonblock", ossl_ssl_read_nonblock, -1);
2598
+ rb_define_method(cSSLSocket, "syswrite", ossl_ssl_write, 1);
2599
+ rb_define_private_method(cSSLSocket, "syswrite_nonblock", ossl_ssl_write_nonblock, -1);
2600
+ rb_define_private_method(cSSLSocket, "stop", ossl_ssl_stop, 0);
2601
+ rb_define_method(cSSLSocket, "cert", ossl_ssl_get_cert, 0);
2602
+ rb_define_method(cSSLSocket, "peer_cert", ossl_ssl_get_peer_cert, 0);
2603
+ rb_define_method(cSSLSocket, "peer_cert_chain", ossl_ssl_get_peer_cert_chain, 0);
2604
+ rb_define_method(cSSLSocket, "ssl_version", ossl_ssl_get_version, 0);
2605
+ rb_define_method(cSSLSocket, "cipher", ossl_ssl_get_cipher, 0);
2606
+ rb_define_method(cSSLSocket, "state", ossl_ssl_get_state, 0);
2607
+ rb_define_method(cSSLSocket, "pending", ossl_ssl_pending, 0);
2608
+ rb_define_method(cSSLSocket, "session_reused?", ossl_ssl_session_reused, 0);
2609
+ /* implementation of OpenSSL::SSL::SSLSocket#session is in lib/openssl/ssl.rb */
2610
+ rb_define_method(cSSLSocket, "session=", ossl_ssl_set_session, 1);
2611
+ rb_define_method(cSSLSocket, "verify_result", ossl_ssl_get_verify_result, 0);
2612
+ rb_define_method(cSSLSocket, "client_ca", ossl_ssl_get_client_ca_list, 0);
2613
+ #ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME
2614
+ /* #hostname is defined in lib/openssl/ssl.rb */
2615
+ rb_define_method(cSSLSocket, "hostname=", ossl_ssl_set_hostname, 1);
2616
+ #endif
2617
+ # ifdef HAVE_SSL_GET_SERVER_TMP_KEY
2618
+ rb_define_method(cSSLSocket, "tmp_key", ossl_ssl_tmp_key, 0);
2619
+ # endif
2620
+ # ifdef HAVE_SSL_CTX_SET_ALPN_SELECT_CB
2621
+ rb_define_method(cSSLSocket, "alpn_protocol", ossl_ssl_alpn_protocol, 0);
2622
+ # endif
2623
+ # ifdef HAVE_SSL_CTX_SET_NEXT_PROTO_SELECT_CB
2624
+ rb_define_method(cSSLSocket, "npn_protocol", ossl_ssl_npn_protocol, 0);
2625
+ # endif
2626
+ #endif
2627
+
2628
+ #define ossl_ssl_def_const(x) rb_define_const(mSSL, #x, LONG2NUM(SSL_##x))
2629
+
2630
+ ossl_ssl_def_const(VERIFY_NONE);
2631
+ ossl_ssl_def_const(VERIFY_PEER);
2632
+ ossl_ssl_def_const(VERIFY_FAIL_IF_NO_PEER_CERT);
2633
+ ossl_ssl_def_const(VERIFY_CLIENT_ONCE);
2634
+ /* Introduce constants included in OP_ALL. These constants are mostly for
2635
+ * unset some bits in OP_ALL such as;
2636
+ * ctx.options = OP_ALL & ~OP_DONT_INSERT_EMPTY_FRAGMENTS
2637
+ */
2638
+ ossl_ssl_def_const(OP_MICROSOFT_SESS_ID_BUG);
2639
+ ossl_ssl_def_const(OP_NETSCAPE_CHALLENGE_BUG);
2640
+ ossl_ssl_def_const(OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG);
2641
+ ossl_ssl_def_const(OP_SSLREF2_REUSE_CERT_TYPE_BUG);
2642
+ ossl_ssl_def_const(OP_MICROSOFT_BIG_SSLV3_BUFFER);
2643
+ ossl_ssl_def_const(OP_MSIE_SSLV2_RSA_PADDING);
2644
+ ossl_ssl_def_const(OP_SSLEAY_080_CLIENT_DH_BUG);
2645
+ ossl_ssl_def_const(OP_TLS_D5_BUG);
2646
+ ossl_ssl_def_const(OP_TLS_BLOCK_PADDING_BUG);
2647
+ ossl_ssl_def_const(OP_DONT_INSERT_EMPTY_FRAGMENTS);
2648
+ ossl_ssl_def_const(OP_ALL);
2649
+ ossl_ssl_def_const(OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
2650
+ ossl_ssl_def_const(OP_SINGLE_ECDH_USE);
2651
+ ossl_ssl_def_const(OP_SINGLE_DH_USE);
2652
+ ossl_ssl_def_const(OP_EPHEMERAL_RSA);
2653
+ ossl_ssl_def_const(OP_CIPHER_SERVER_PREFERENCE);
2654
+ ossl_ssl_def_const(OP_TLS_ROLLBACK_BUG);
2655
+ ossl_ssl_def_const(OP_NO_SSLv2);
2656
+ ossl_ssl_def_const(OP_NO_SSLv3);
2657
+ ossl_ssl_def_const(OP_NO_TLSv1);
2658
+ #if defined(SSL_OP_NO_TLSv1_1)
2659
+ ossl_ssl_def_const(OP_NO_TLSv1_1);
2660
+ #endif
2661
+ #if defined(SSL_OP_NO_TLSv1_2)
2662
+ ossl_ssl_def_const(OP_NO_TLSv1_2);
2663
+ #endif
2664
+ #if defined(SSL_OP_NO_TICKET)
2665
+ ossl_ssl_def_const(OP_NO_TICKET);
2666
+ #endif
2667
+ #if defined(SSL_OP_NO_COMPRESSION)
2668
+ ossl_ssl_def_const(OP_NO_COMPRESSION);
2669
+ #endif
2670
+ ossl_ssl_def_const(OP_PKCS1_CHECK_1);
2671
+ ossl_ssl_def_const(OP_PKCS1_CHECK_2);
2672
+ ossl_ssl_def_const(OP_NETSCAPE_CA_DN_BUG);
2673
+ ossl_ssl_def_const(OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG);
2674
+
2675
+ #undef rb_intern
2676
+ sym_exception = ID2SYM(rb_intern("exception"));
2677
+ sym_wait_readable = ID2SYM(rb_intern("wait_readable"));
2678
+ sym_wait_writable = ID2SYM(rb_intern("wait_writable"));
2679
+ }