rubysl-openssl 1.0.2 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +5 -6
- data/ext/rubysl/openssl/.gitignore +3 -0
- data/ext/rubysl/openssl/deprecation.rb +21 -0
- data/ext/rubysl/openssl/extconf.rb +45 -32
- data/ext/rubysl/openssl/openssl_missing.c +20 -7
- data/ext/rubysl/openssl/openssl_missing.h +22 -15
- data/ext/rubysl/openssl/ossl.c +610 -61
- data/ext/rubysl/openssl/ossl.h +31 -17
- data/ext/rubysl/openssl/ossl_asn1.c +974 -183
- data/ext/rubysl/openssl/ossl_asn1.h +3 -3
- data/ext/rubysl/openssl/ossl_bio.c +4 -3
- data/ext/rubysl/openssl/ossl_bio.h +1 -1
- data/ext/rubysl/openssl/ossl_bn.c +32 -28
- data/ext/rubysl/openssl/ossl_bn.h +1 -1
- data/ext/rubysl/openssl/ossl_cipher.c +494 -93
- data/ext/rubysl/openssl/ossl_cipher.h +1 -1
- data/ext/rubysl/openssl/ossl_config.c +4 -5
- data/ext/rubysl/openssl/ossl_config.h +1 -1
- data/ext/rubysl/openssl/ossl_digest.c +206 -24
- data/ext/rubysl/openssl/ossl_digest.h +1 -1
- data/ext/rubysl/openssl/ossl_engine.c +48 -26
- data/ext/rubysl/openssl/ossl_engine.h +1 -1
- data/ext/rubysl/openssl/ossl_hmac.c +40 -38
- data/ext/rubysl/openssl/ossl_hmac.h +1 -1
- data/ext/rubysl/openssl/ossl_ns_spki.c +157 -25
- data/ext/rubysl/openssl/ossl_ns_spki.h +1 -1
- data/ext/rubysl/openssl/ossl_ocsp.c +57 -40
- data/ext/rubysl/openssl/ossl_ocsp.h +1 -1
- data/ext/rubysl/openssl/ossl_pkcs12.c +15 -13
- data/ext/rubysl/openssl/ossl_pkcs12.h +1 -1
- data/ext/rubysl/openssl/ossl_pkcs5.c +108 -18
- data/ext/rubysl/openssl/ossl_pkcs7.c +44 -37
- data/ext/rubysl/openssl/ossl_pkcs7.h +1 -1
- data/ext/rubysl/openssl/ossl_pkey.c +211 -15
- data/ext/rubysl/openssl/ossl_pkey.h +19 -9
- data/ext/rubysl/openssl/ossl_pkey_dh.c +180 -47
- data/ext/rubysl/openssl/ossl_pkey_dsa.c +184 -47
- data/ext/rubysl/openssl/ossl_pkey_ec.c +177 -93
- data/ext/rubysl/openssl/ossl_pkey_rsa.c +209 -102
- data/ext/rubysl/openssl/ossl_rand.c +15 -15
- data/ext/rubysl/openssl/ossl_rand.h +1 -1
- data/ext/rubysl/openssl/ossl_ssl.c +939 -192
- data/ext/rubysl/openssl/ossl_ssl.h +6 -6
- data/ext/rubysl/openssl/ossl_ssl_session.c +78 -62
- data/ext/rubysl/openssl/ossl_version.h +2 -2
- data/ext/rubysl/openssl/ossl_x509.c +1 -1
- data/ext/rubysl/openssl/ossl_x509.h +1 -1
- data/ext/rubysl/openssl/ossl_x509attr.c +20 -19
- data/ext/rubysl/openssl/ossl_x509cert.c +169 -67
- data/ext/rubysl/openssl/ossl_x509crl.c +41 -39
- data/ext/rubysl/openssl/ossl_x509ext.c +51 -38
- data/ext/rubysl/openssl/ossl_x509name.c +139 -29
- data/ext/rubysl/openssl/ossl_x509req.c +42 -40
- data/ext/rubysl/openssl/ossl_x509revoked.c +20 -20
- data/ext/rubysl/openssl/ossl_x509store.c +99 -47
- data/ext/rubysl/openssl/ruby_missing.h +3 -16
- data/lib/openssl/bn.rb +19 -19
- data/lib/openssl/buffering.rb +222 -14
- data/lib/openssl/cipher.rb +20 -20
- data/lib/openssl/config.rb +1 -4
- data/lib/openssl/digest.rb +47 -19
- data/lib/openssl/ssl.rb +197 -1
- data/lib/openssl/x509.rb +162 -1
- data/lib/rubysl/openssl.rb +4 -8
- data/lib/rubysl/openssl/version.rb +1 -1
- data/rubysl-openssl.gemspec +1 -2
- metadata +16 -34
- data/ext/rubysl/openssl/extconf.h +0 -50
- data/lib/openssl/net/ftptls.rb +0 -53
- data/lib/openssl/net/telnets.rb +0 -251
- data/lib/openssl/pkcs7.rb +0 -25
- data/lib/openssl/ssl-internal.rb +0 -187
- data/lib/openssl/x509-internal.rb +0 -153
@@ -1,5 +1,5 @@
|
|
1
1
|
/*
|
2
|
-
* $Id
|
2
|
+
* $Id$
|
3
3
|
* 'OpenSSL for Ruby' project
|
4
4
|
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
|
5
5
|
* All rights reserved.
|
@@ -37,7 +37,7 @@ static VALUE
|
|
37
37
|
ossl_rand_seed(VALUE self, VALUE str)
|
38
38
|
{
|
39
39
|
StringValue(str);
|
40
|
-
RAND_seed(RSTRING_PTR(str),
|
40
|
+
RAND_seed(RSTRING_PTR(str), RSTRING_LENINT(str));
|
41
41
|
|
42
42
|
return str;
|
43
43
|
}
|
@@ -51,7 +51,7 @@ static VALUE
|
|
51
51
|
ossl_rand_add(VALUE self, VALUE str, VALUE entropy)
|
52
52
|
{
|
53
53
|
StringValue(str);
|
54
|
-
RAND_add(RSTRING_PTR(str),
|
54
|
+
RAND_add(RSTRING_PTR(str), RSTRING_LENINT(str), NUM2DBL(entropy));
|
55
55
|
|
56
56
|
return self;
|
57
57
|
}
|
@@ -65,7 +65,7 @@ static VALUE
|
|
65
65
|
ossl_rand_load_file(VALUE self, VALUE filename)
|
66
66
|
{
|
67
67
|
SafeStringValue(filename);
|
68
|
-
|
68
|
+
|
69
69
|
if(!RAND_load_file(RSTRING_PTR(filename), -1)) {
|
70
70
|
ossl_raise(eRandomError, NULL);
|
71
71
|
}
|
@@ -99,7 +99,7 @@ ossl_rand_bytes(VALUE self, VALUE len)
|
|
99
99
|
int n = NUM2INT(len);
|
100
100
|
|
101
101
|
str = rb_str_new(0, n);
|
102
|
-
if (!RAND_bytes(RSTRING_PTR(str), n)) {
|
102
|
+
if (!RAND_bytes((unsigned char *)RSTRING_PTR(str), n)) {
|
103
103
|
ossl_raise(eRandomError, NULL);
|
104
104
|
}
|
105
105
|
|
@@ -118,7 +118,7 @@ ossl_rand_pseudo_bytes(VALUE self, VALUE len)
|
|
118
118
|
int n = NUM2INT(len);
|
119
119
|
|
120
120
|
str = rb_str_new(0, n);
|
121
|
-
if (!RAND_pseudo_bytes(RSTRING_PTR(str), n)) {
|
121
|
+
if (!RAND_pseudo_bytes((unsigned char *)RSTRING_PTR(str), n)) {
|
122
122
|
ossl_raise(eRandomError, NULL);
|
123
123
|
}
|
124
124
|
|
@@ -134,7 +134,7 @@ static VALUE
|
|
134
134
|
ossl_rand_egd(VALUE self, VALUE filename)
|
135
135
|
{
|
136
136
|
SafeStringValue(filename);
|
137
|
-
|
137
|
+
|
138
138
|
if(!RAND_egd(RSTRING_PTR(filename))) {
|
139
139
|
ossl_raise(eRandomError, NULL);
|
140
140
|
}
|
@@ -149,7 +149,7 @@ ossl_rand_egd(VALUE self, VALUE filename)
|
|
149
149
|
static VALUE
|
150
150
|
ossl_rand_egd_bytes(VALUE self, VALUE filename, VALUE len)
|
151
151
|
{
|
152
|
-
|
152
|
+
int n = NUM2INT(len);
|
153
153
|
|
154
154
|
SafeStringValue(filename);
|
155
155
|
|
@@ -172,8 +172,8 @@ ossl_rand_status(VALUE self)
|
|
172
172
|
}
|
173
173
|
|
174
174
|
#define DEFMETH(class, name, func, argc) \
|
175
|
-
rb_define_method(class, name, func, argc); \
|
176
|
-
rb_define_singleton_method(class, name, func, argc);
|
175
|
+
rb_define_method((class), (name), (func), (argc)); \
|
176
|
+
rb_define_singleton_method((class), (name), (func), (argc));
|
177
177
|
|
178
178
|
/*
|
179
179
|
* INIT
|
@@ -181,14 +181,14 @@ ossl_rand_status(VALUE self)
|
|
181
181
|
void
|
182
182
|
Init_ossl_rand()
|
183
183
|
{
|
184
|
-
#if 0
|
185
|
-
mOSSL = rb_define_module("OpenSSL");
|
184
|
+
#if 0
|
185
|
+
mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
|
186
186
|
#endif
|
187
187
|
|
188
188
|
mRandom = rb_define_module_under(mOSSL, "Random");
|
189
|
-
|
189
|
+
|
190
190
|
eRandomError = rb_define_class_under(mRandom, "RandomError", eOSSLError);
|
191
|
-
|
191
|
+
|
192
192
|
DEFMETH(mRandom, "seed", ossl_rand_seed, 1);
|
193
193
|
DEFMETH(mRandom, "random_add", ossl_rand_add, 2);
|
194
194
|
DEFMETH(mRandom, "load_random_file", ossl_rand_load_file, 1);
|
@@ -196,7 +196,7 @@ Init_ossl_rand()
|
|
196
196
|
DEFMETH(mRandom, "random_bytes", ossl_rand_bytes, 1);
|
197
197
|
DEFMETH(mRandom, "pseudo_bytes", ossl_rand_pseudo_bytes, 1);
|
198
198
|
DEFMETH(mRandom, "egd", ossl_rand_egd, 1);
|
199
|
-
DEFMETH(mRandom, "egd_bytes", ossl_rand_egd_bytes, 2);
|
199
|
+
DEFMETH(mRandom, "egd_bytes", ossl_rand_egd_bytes, 2);
|
200
200
|
DEFMETH(mRandom, "status?", ossl_rand_status, 0)
|
201
201
|
}
|
202
202
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/*
|
2
|
-
* $Id
|
2
|
+
* $Id$
|
3
3
|
* 'OpenSSL for Ruby' project
|
4
4
|
* Copyright (C) 2000-2002 GOTOU Yuuzou <gotoyuzo@notwork.org>
|
5
5
|
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
|
@@ -11,19 +11,17 @@
|
|
11
11
|
* (See the file 'LICENCE'.)
|
12
12
|
*/
|
13
13
|
#include "ossl.h"
|
14
|
-
#include <rubysig.h>
|
15
|
-
#include <rubyio.h>
|
16
14
|
|
17
15
|
#if defined(HAVE_UNISTD_H)
|
18
16
|
# include <unistd.h> /* for read(), and write() */
|
19
17
|
#endif
|
20
18
|
|
21
|
-
#define numberof(ary) (sizeof(ary)/sizeof(ary[0]))
|
19
|
+
#define numberof(ary) (int)(sizeof(ary)/sizeof((ary)[0]))
|
22
20
|
|
23
21
|
#ifdef _WIN32
|
24
22
|
# define TO_SOCKET(s) _get_osfhandle(s)
|
25
23
|
#else
|
26
|
-
# define TO_SOCKET(s) s
|
24
|
+
# define TO_SOCKET(s) (s)
|
27
25
|
#endif
|
28
26
|
|
29
27
|
VALUE mSSL;
|
@@ -31,44 +29,51 @@ VALUE eSSLError;
|
|
31
29
|
VALUE cSSLContext;
|
32
30
|
VALUE cSSLSocket;
|
33
31
|
|
34
|
-
#define ossl_sslctx_set_cert(o,v)
|
35
|
-
#define ossl_sslctx_set_key(o,v)
|
36
|
-
#define ossl_sslctx_set_client_ca(o,v)
|
37
|
-
#define ossl_sslctx_set_ca_file(o,v)
|
38
|
-
#define ossl_sslctx_set_ca_path(o,v)
|
39
|
-
#define ossl_sslctx_set_timeout(o,v)
|
40
|
-
#define ossl_sslctx_set_verify_mode(o,v)
|
41
|
-
#define ossl_sslctx_set_verify_dep(o,v)
|
42
|
-
#define ossl_sslctx_set_verify_cb(o,v)
|
43
|
-
#define ossl_sslctx_set_options(o,v)
|
44
|
-
#define ossl_sslctx_set_cert_store(o,v)
|
45
|
-
#define ossl_sslctx_set_extra_cert(o,v)
|
46
|
-
#define ossl_sslctx_set_client_cert_cb(o,v)
|
47
|
-
#define ossl_sslctx_set_tmp_dh_cb(o,v)
|
48
|
-
#define ossl_sslctx_set_sess_id_ctx(o, v)
|
49
|
-
|
50
|
-
#define ossl_sslctx_get_cert(o)
|
51
|
-
#define ossl_sslctx_get_key(o)
|
52
|
-
#define ossl_sslctx_get_client_ca(o)
|
53
|
-
#define ossl_sslctx_get_ca_file(o)
|
54
|
-
#define ossl_sslctx_get_ca_path(o)
|
55
|
-
#define ossl_sslctx_get_timeout(o)
|
56
|
-
#define ossl_sslctx_get_verify_mode(o)
|
57
|
-
#define ossl_sslctx_get_verify_dep(o)
|
58
|
-
#define ossl_sslctx_get_verify_cb(o)
|
59
|
-
#define ossl_sslctx_get_options(o)
|
60
|
-
#define ossl_sslctx_get_cert_store(o)
|
61
|
-
#define ossl_sslctx_get_extra_cert(o)
|
62
|
-
#define ossl_sslctx_get_client_cert_cb(o)
|
63
|
-
#define ossl_sslctx_get_tmp_dh_cb(o)
|
64
|
-
#define ossl_sslctx_get_sess_id_ctx(o)
|
32
|
+
#define ossl_sslctx_set_cert(o,v) rb_iv_set((o),"@cert",(v))
|
33
|
+
#define ossl_sslctx_set_key(o,v) rb_iv_set((o),"@key",(v))
|
34
|
+
#define ossl_sslctx_set_client_ca(o,v) rb_iv_set((o),"@client_ca",(v))
|
35
|
+
#define ossl_sslctx_set_ca_file(o,v) rb_iv_set((o),"@ca_file",(v))
|
36
|
+
#define ossl_sslctx_set_ca_path(o,v) rb_iv_set((o),"@ca_path",(v))
|
37
|
+
#define ossl_sslctx_set_timeout(o,v) rb_iv_set((o),"@timeout",(v))
|
38
|
+
#define ossl_sslctx_set_verify_mode(o,v) rb_iv_set((o),"@verify_mode",(v))
|
39
|
+
#define ossl_sslctx_set_verify_dep(o,v) rb_iv_set((o),"@verify_depth",(v))
|
40
|
+
#define ossl_sslctx_set_verify_cb(o,v) rb_iv_set((o),"@verify_callback",(v))
|
41
|
+
#define ossl_sslctx_set_options(o,v) rb_iv_set((o),"@options",(v))
|
42
|
+
#define ossl_sslctx_set_cert_store(o,v) rb_iv_set((o),"@cert_store",(v))
|
43
|
+
#define ossl_sslctx_set_extra_cert(o,v) rb_iv_set((o),"@extra_chain_cert",(v))
|
44
|
+
#define ossl_sslctx_set_client_cert_cb(o,v) rb_iv_set((o),"@client_cert_cb",(v))
|
45
|
+
#define ossl_sslctx_set_tmp_dh_cb(o,v) rb_iv_set((o),"@tmp_dh_callback",(v))
|
46
|
+
#define ossl_sslctx_set_sess_id_ctx(o, v) rb_iv_set((o),"@session_id_context",(v))
|
47
|
+
|
48
|
+
#define ossl_sslctx_get_cert(o) rb_iv_get((o),"@cert")
|
49
|
+
#define ossl_sslctx_get_key(o) rb_iv_get((o),"@key")
|
50
|
+
#define ossl_sslctx_get_client_ca(o) rb_iv_get((o),"@client_ca")
|
51
|
+
#define ossl_sslctx_get_ca_file(o) rb_iv_get((o),"@ca_file")
|
52
|
+
#define ossl_sslctx_get_ca_path(o) rb_iv_get((o),"@ca_path")
|
53
|
+
#define ossl_sslctx_get_timeout(o) rb_iv_get((o),"@timeout")
|
54
|
+
#define ossl_sslctx_get_verify_mode(o) rb_iv_get((o),"@verify_mode")
|
55
|
+
#define ossl_sslctx_get_verify_dep(o) rb_iv_get((o),"@verify_depth")
|
56
|
+
#define ossl_sslctx_get_verify_cb(o) rb_iv_get((o),"@verify_callback")
|
57
|
+
#define ossl_sslctx_get_options(o) rb_iv_get((o),"@options")
|
58
|
+
#define ossl_sslctx_get_cert_store(o) rb_iv_get((o),"@cert_store")
|
59
|
+
#define ossl_sslctx_get_extra_cert(o) rb_iv_get((o),"@extra_chain_cert")
|
60
|
+
#define ossl_sslctx_get_client_cert_cb(o) rb_iv_get((o),"@client_cert_cb")
|
61
|
+
#define ossl_sslctx_get_tmp_dh_cb(o) rb_iv_get((o),"@tmp_dh_callback")
|
62
|
+
#define ossl_sslctx_get_sess_id_ctx(o) rb_iv_get((o),"@session_id_context")
|
65
63
|
|
66
64
|
static const char *ossl_sslctx_attrs[] = {
|
67
65
|
"cert", "key", "client_ca", "ca_file", "ca_path",
|
68
|
-
"timeout", "verify_mode", "verify_depth",
|
66
|
+
"timeout", "verify_mode", "verify_depth", "renegotiation_cb",
|
69
67
|
"verify_callback", "options", "cert_store", "extra_chain_cert",
|
70
68
|
"client_cert_cb", "tmp_dh_callback", "session_id_context",
|
71
69
|
"session_get_cb", "session_new_cb", "session_remove_cb",
|
70
|
+
#ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME
|
71
|
+
"servername_cb",
|
72
|
+
#endif
|
73
|
+
#ifdef HAVE_OPENSSL_NPN_NEGOTIATED
|
74
|
+
"npn_protocols",
|
75
|
+
"npn_select_cb",
|
76
|
+
#endif
|
72
77
|
};
|
73
78
|
|
74
79
|
#define ossl_ssl_get_io(o) rb_iv_get((o),"@io")
|
@@ -86,7 +91,12 @@ static const char *ossl_sslctx_attrs[] = {
|
|
86
91
|
#define ossl_ssl_set_tmp_dh(o,v) rb_iv_set((o),"@tmp_dh",(v))
|
87
92
|
|
88
93
|
static const char *ossl_ssl_attr_readers[] = { "io", "context", };
|
89
|
-
static const char *ossl_ssl_attrs[] = {
|
94
|
+
static const char *ossl_ssl_attrs[] = {
|
95
|
+
#ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME
|
96
|
+
"hostname",
|
97
|
+
#endif
|
98
|
+
"sync_close",
|
99
|
+
};
|
90
100
|
|
91
101
|
ID ID_callback_state;
|
92
102
|
|
@@ -97,12 +107,24 @@ struct {
|
|
97
107
|
const char *name;
|
98
108
|
SSL_METHOD *(*func)(void);
|
99
109
|
} ossl_ssl_method_tab[] = {
|
100
|
-
#define OSSL_SSL_METHOD_ENTRY(name) { #name, name##_method }
|
110
|
+
#define OSSL_SSL_METHOD_ENTRY(name) { #name, (SSL_METHOD *(*)(void))name##_method }
|
101
111
|
OSSL_SSL_METHOD_ENTRY(TLSv1),
|
102
112
|
OSSL_SSL_METHOD_ENTRY(TLSv1_server),
|
103
113
|
OSSL_SSL_METHOD_ENTRY(TLSv1_client),
|
114
|
+
#if defined(HAVE_TLSV1_2_METHOD) && defined(HAVE_TLSV1_2_SERVER_METHOD) && \
|
115
|
+
defined(HAVE_TLSV1_2_CLIENT_METHOD)
|
116
|
+
OSSL_SSL_METHOD_ENTRY(TLSv1_2),
|
117
|
+
OSSL_SSL_METHOD_ENTRY(TLSv1_2_server),
|
118
|
+
OSSL_SSL_METHOD_ENTRY(TLSv1_2_client),
|
119
|
+
#endif
|
120
|
+
#if defined(HAVE_TLSV1_1_METHOD) && defined(HAVE_TLSV1_1_SERVER_METHOD) && \
|
121
|
+
defined(HAVE_TLSV1_1_CLIENT_METHOD)
|
122
|
+
OSSL_SSL_METHOD_ENTRY(TLSv1_1),
|
123
|
+
OSSL_SSL_METHOD_ENTRY(TLSv1_1_server),
|
124
|
+
OSSL_SSL_METHOD_ENTRY(TLSv1_1_client),
|
125
|
+
#endif
|
104
126
|
#if defined(HAVE_SSLV2_METHOD) && defined(HAVE_SSLV2_SERVER_METHOD) && \
|
105
|
-
defined(HAVE_SSLV2_CLIENT_METHOD)
|
127
|
+
defined(HAVE_SSLV2_CLIENT_METHOD)
|
106
128
|
OSSL_SSL_METHOD_ENTRY(SSLv2),
|
107
129
|
OSSL_SSL_METHOD_ENTRY(SSLv2_server),
|
108
130
|
OSSL_SSL_METHOD_ENTRY(SSLv2_client),
|
@@ -134,15 +156,27 @@ static VALUE
|
|
134
156
|
ossl_sslctx_s_alloc(VALUE klass)
|
135
157
|
{
|
136
158
|
SSL_CTX *ctx;
|
159
|
+
long mode = SSL_MODE_ENABLE_PARTIAL_WRITE;
|
160
|
+
|
161
|
+
#ifdef SSL_MODE_RELEASE_BUFFERS
|
162
|
+
mode |= SSL_MODE_RELEASE_BUFFERS;
|
163
|
+
#endif
|
137
164
|
|
138
165
|
ctx = SSL_CTX_new(SSLv23_method());
|
139
166
|
if (!ctx) {
|
140
|
-
ossl_raise(eSSLError, "SSL_CTX_new
|
167
|
+
ossl_raise(eSSLError, "SSL_CTX_new");
|
141
168
|
}
|
142
|
-
SSL_CTX_set_mode(ctx,
|
169
|
+
SSL_CTX_set_mode(ctx, mode);
|
143
170
|
return Data_Wrap_Struct(klass, 0, ossl_sslctx_free, ctx);
|
144
171
|
}
|
145
172
|
|
173
|
+
/*
|
174
|
+
* call-seq:
|
175
|
+
* ctx.ssl_version = :TLSv1
|
176
|
+
* ctx.ssl_version = "SSLv23_client"
|
177
|
+
*
|
178
|
+
* You can get a list of valid versions with OpenSSL::SSL::SSLContext::METHODS
|
179
|
+
*/
|
146
180
|
static VALUE
|
147
181
|
ossl_sslctx_set_ssl_version(VALUE self, VALUE ssl_method)
|
148
182
|
{
|
@@ -166,7 +200,7 @@ ossl_sslctx_set_ssl_version(VALUE self, VALUE ssl_method)
|
|
166
200
|
}
|
167
201
|
Data_Get_Struct(self, SSL_CTX, ctx);
|
168
202
|
if (SSL_CTX_set_ssl_version(ctx, method) != 1) {
|
169
|
-
ossl_raise(eSSLError, "SSL_CTX_set_ssl_version
|
203
|
+
ossl_raise(eSSLError, "SSL_CTX_set_ssl_version");
|
170
204
|
}
|
171
205
|
|
172
206
|
return ssl_method;
|
@@ -221,13 +255,12 @@ ossl_call_client_cert_cb(VALUE obj)
|
|
221
255
|
static int
|
222
256
|
ossl_client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
|
223
257
|
{
|
224
|
-
VALUE obj;
|
225
|
-
int status, success;
|
258
|
+
VALUE obj, success;
|
226
259
|
|
227
260
|
obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
|
228
261
|
success = rb_protect((VALUE(*)_((VALUE)))ossl_call_client_cert_cb,
|
229
|
-
obj,
|
230
|
-
if (
|
262
|
+
obj, NULL);
|
263
|
+
if (!RTEST(success)) return 0;
|
231
264
|
*x509 = DupX509CertPtr(ossl_ssl_get_x509(obj));
|
232
265
|
*pkey = DupPKeyPtr(ossl_ssl_get_key(obj));
|
233
266
|
|
@@ -256,15 +289,14 @@ ossl_call_tmp_dh_callback(VALUE *args)
|
|
256
289
|
static DH*
|
257
290
|
ossl_tmp_dh_callback(SSL *ssl, int is_export, int keylength)
|
258
291
|
{
|
259
|
-
VALUE args[3];
|
260
|
-
int status, success;
|
292
|
+
VALUE args[3], success;
|
261
293
|
|
262
294
|
args[0] = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
|
263
295
|
args[1] = INT2FIX(is_export);
|
264
296
|
args[2] = INT2FIX(keylength);
|
265
297
|
success = rb_protect((VALUE(*)_((VALUE)))ossl_call_tmp_dh_callback,
|
266
|
-
(VALUE)args,
|
267
|
-
if (
|
298
|
+
(VALUE)args, NULL);
|
299
|
+
if (!RTEST(success)) return NULL;
|
268
300
|
|
269
301
|
return GetPKeyPtr(ossl_ssl_get_tmp_dh(args[0]))->pkey.dh;
|
270
302
|
}
|
@@ -299,8 +331,8 @@ ossl_ssl_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
|
|
299
331
|
static VALUE
|
300
332
|
ossl_call_session_get_cb(VALUE ary)
|
301
333
|
{
|
302
|
-
VALUE ssl_obj, sslctx_obj, cb
|
303
|
-
|
334
|
+
VALUE ssl_obj, sslctx_obj, cb;
|
335
|
+
|
304
336
|
Check_Type(ary, T_ARRAY);
|
305
337
|
ssl_obj = rb_ary_entry(ary, 0);
|
306
338
|
|
@@ -327,7 +359,7 @@ ossl_sslctx_session_get_cb(SSL *ssl, unsigned char *buf, int len, int *copy)
|
|
327
359
|
ssl_obj = (VALUE)ptr;
|
328
360
|
ary = rb_ary_new2(2);
|
329
361
|
rb_ary_push(ary, ssl_obj);
|
330
|
-
rb_ary_push(ary, rb_str_new(buf, len));
|
362
|
+
rb_ary_push(ary, rb_str_new((const char *)buf, len));
|
331
363
|
|
332
364
|
ret_obj = rb_protect((VALUE(*)_((VALUE)))ossl_call_session_get_cb, ary, &state);
|
333
365
|
if (state) {
|
@@ -346,8 +378,8 @@ ossl_sslctx_session_get_cb(SSL *ssl, unsigned char *buf, int len, int *copy)
|
|
346
378
|
static VALUE
|
347
379
|
ossl_call_session_new_cb(VALUE ary)
|
348
380
|
{
|
349
|
-
VALUE ssl_obj, sslctx_obj, cb
|
350
|
-
|
381
|
+
VALUE ssl_obj, sslctx_obj, cb;
|
382
|
+
|
351
383
|
Check_Type(ary, T_ARRAY);
|
352
384
|
ssl_obj = rb_ary_entry(ary, 0);
|
353
385
|
|
@@ -363,7 +395,7 @@ ossl_call_session_new_cb(VALUE ary)
|
|
363
395
|
static int
|
364
396
|
ossl_sslctx_session_new_cb(SSL *ssl, SSL_SESSION *sess)
|
365
397
|
{
|
366
|
-
VALUE ary, ssl_obj, sess_obj
|
398
|
+
VALUE ary, ssl_obj, sess_obj;
|
367
399
|
void *ptr;
|
368
400
|
int state = 0;
|
369
401
|
|
@@ -380,20 +412,26 @@ ossl_sslctx_session_new_cb(SSL *ssl, SSL_SESSION *sess)
|
|
380
412
|
rb_ary_push(ary, ssl_obj);
|
381
413
|
rb_ary_push(ary, sess_obj);
|
382
414
|
|
383
|
-
|
415
|
+
rb_protect((VALUE(*)_((VALUE)))ossl_call_session_new_cb, ary, &state);
|
384
416
|
if (state) {
|
385
417
|
rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(state));
|
386
|
-
return 0; /* what should be returned here??? */
|
387
418
|
}
|
388
419
|
|
389
|
-
|
420
|
+
/*
|
421
|
+
* return 0 which means to OpenSSL that the the session is still
|
422
|
+
* valid (since we created Ruby Session object) and was not freed by us
|
423
|
+
* with SSL_SESSION_free(). Call SSLContext#remove_session(sess) in
|
424
|
+
* session_get_cb block if you don't want OpenSSL to cache the session
|
425
|
+
* internally.
|
426
|
+
*/
|
427
|
+
return 0;
|
390
428
|
}
|
391
429
|
|
392
430
|
static VALUE
|
393
431
|
ossl_call_session_remove_cb(VALUE ary)
|
394
432
|
{
|
395
|
-
VALUE sslctx_obj, cb
|
396
|
-
|
433
|
+
VALUE sslctx_obj, cb;
|
434
|
+
|
397
435
|
Check_Type(ary, T_ARRAY);
|
398
436
|
sslctx_obj = rb_ary_entry(ary, 0);
|
399
437
|
|
@@ -406,7 +444,7 @@ ossl_call_session_remove_cb(VALUE ary)
|
|
406
444
|
static void
|
407
445
|
ossl_sslctx_session_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
|
408
446
|
{
|
409
|
-
VALUE ary, sslctx_obj, sess_obj
|
447
|
+
VALUE ary, sslctx_obj, sess_obj;
|
410
448
|
void *ptr;
|
411
449
|
int state = 0;
|
412
450
|
|
@@ -423,7 +461,7 @@ ossl_sslctx_session_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
|
|
423
461
|
rb_ary_push(ary, sslctx_obj);
|
424
462
|
rb_ary_push(ary, sess_obj);
|
425
463
|
|
426
|
-
|
464
|
+
rb_protect((VALUE(*)_((VALUE)))ossl_call_session_remove_cb, ary, &state);
|
427
465
|
if (state) {
|
428
466
|
/*
|
429
467
|
the SSL_CTX is frozen, nowhere to save state.
|
@@ -448,13 +486,167 @@ ossl_sslctx_add_extra_chain_cert_i(VALUE i, VALUE arg)
|
|
448
486
|
return i;
|
449
487
|
}
|
450
488
|
|
489
|
+
static VALUE ossl_sslctx_setup(VALUE self);
|
490
|
+
|
491
|
+
#ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME
|
492
|
+
static VALUE
|
493
|
+
ossl_call_servername_cb(VALUE ary)
|
494
|
+
{
|
495
|
+
VALUE ssl_obj, sslctx_obj, cb, ret_obj;
|
496
|
+
|
497
|
+
Check_Type(ary, T_ARRAY);
|
498
|
+
ssl_obj = rb_ary_entry(ary, 0);
|
499
|
+
|
500
|
+
sslctx_obj = rb_iv_get(ssl_obj, "@context");
|
501
|
+
if (NIL_P(sslctx_obj)) return Qnil;
|
502
|
+
cb = rb_iv_get(sslctx_obj, "@servername_cb");
|
503
|
+
if (NIL_P(cb)) return Qnil;
|
504
|
+
|
505
|
+
ret_obj = rb_funcall(cb, rb_intern("call"), 1, ary);
|
506
|
+
if (rb_obj_is_kind_of(ret_obj, cSSLContext)) {
|
507
|
+
SSL *ssl;
|
508
|
+
SSL_CTX *ctx2;
|
509
|
+
|
510
|
+
ossl_sslctx_setup(ret_obj);
|
511
|
+
Data_Get_Struct(ssl_obj, SSL, ssl);
|
512
|
+
Data_Get_Struct(ret_obj, SSL_CTX, ctx2);
|
513
|
+
SSL_set_SSL_CTX(ssl, ctx2);
|
514
|
+
} else if (!NIL_P(ret_obj)) {
|
515
|
+
ossl_raise(rb_eArgError, "servername_cb must return an OpenSSL::SSL::SSLContext object or nil");
|
516
|
+
}
|
517
|
+
|
518
|
+
return ret_obj;
|
519
|
+
}
|
520
|
+
|
521
|
+
static int
|
522
|
+
ssl_servername_cb(SSL *ssl, int *ad, void *arg)
|
523
|
+
{
|
524
|
+
VALUE ary, ssl_obj;
|
525
|
+
void *ptr;
|
526
|
+
int state = 0;
|
527
|
+
const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
|
528
|
+
|
529
|
+
if (!servername)
|
530
|
+
return SSL_TLSEXT_ERR_OK;
|
531
|
+
|
532
|
+
if ((ptr = SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx)) == NULL)
|
533
|
+
return SSL_TLSEXT_ERR_ALERT_FATAL;
|
534
|
+
ssl_obj = (VALUE)ptr;
|
535
|
+
ary = rb_ary_new2(2);
|
536
|
+
rb_ary_push(ary, ssl_obj);
|
537
|
+
rb_ary_push(ary, rb_str_new2(servername));
|
538
|
+
|
539
|
+
rb_protect((VALUE(*)_((VALUE)))ossl_call_servername_cb, ary, &state);
|
540
|
+
if (state) {
|
541
|
+
rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(state));
|
542
|
+
return SSL_TLSEXT_ERR_ALERT_FATAL;
|
543
|
+
}
|
544
|
+
|
545
|
+
return SSL_TLSEXT_ERR_OK;
|
546
|
+
}
|
547
|
+
#endif
|
548
|
+
|
549
|
+
static void
|
550
|
+
ssl_renegotiation_cb(const SSL *ssl)
|
551
|
+
{
|
552
|
+
VALUE ssl_obj, sslctx_obj, cb;
|
553
|
+
void *ptr;
|
554
|
+
|
555
|
+
if ((ptr = SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx)) == NULL)
|
556
|
+
ossl_raise(eSSLError, "SSL object could not be retrieved");
|
557
|
+
ssl_obj = (VALUE)ptr;
|
558
|
+
|
559
|
+
sslctx_obj = rb_iv_get(ssl_obj, "@context");
|
560
|
+
if (NIL_P(sslctx_obj)) return;
|
561
|
+
cb = rb_iv_get(sslctx_obj, "@renegotiation_cb");
|
562
|
+
if (NIL_P(cb)) return;
|
563
|
+
|
564
|
+
(void) rb_funcall(cb, rb_intern("call"), 1, ssl_obj);
|
565
|
+
}
|
566
|
+
|
567
|
+
#ifdef HAVE_OPENSSL_NPN_NEGOTIATED
|
568
|
+
static VALUE
|
569
|
+
ssl_npn_encode_protocol_i(VALUE cur, VALUE encoded)
|
570
|
+
{
|
571
|
+
int len = RSTRING_LENINT(cur);
|
572
|
+
char len_byte;
|
573
|
+
if (len < 1 || len > 255)
|
574
|
+
ossl_raise(eSSLError, "Advertised protocol must have length 1..255");
|
575
|
+
/* Encode the length byte */
|
576
|
+
len_byte = len;
|
577
|
+
rb_str_buf_cat(encoded, &len_byte, 1);
|
578
|
+
rb_str_buf_cat(encoded, RSTRING_PTR(cur), len);
|
579
|
+
return Qnil;
|
580
|
+
}
|
581
|
+
|
582
|
+
static void
|
583
|
+
ssl_npn_encode_protocols(VALUE sslctx, VALUE protocols)
|
584
|
+
{
|
585
|
+
VALUE encoded = rb_str_new2("");
|
586
|
+
rb_iterate(rb_each, protocols, ssl_npn_encode_protocol_i, encoded);
|
587
|
+
StringValueCStr(encoded);
|
588
|
+
rb_iv_set(sslctx, "@_protocols", encoded);
|
589
|
+
}
|
590
|
+
|
591
|
+
static int
|
592
|
+
ssl_npn_advertise_cb(SSL *ssl, const unsigned char **out, unsigned int *outlen, void *arg)
|
593
|
+
{
|
594
|
+
VALUE sslctx_obj = (VALUE) arg;
|
595
|
+
VALUE protocols = rb_iv_get(sslctx_obj, "@_protocols");
|
596
|
+
|
597
|
+
*out = (const unsigned char *) RSTRING_PTR(protocols);
|
598
|
+
*outlen = RSTRING_LENINT(protocols);
|
599
|
+
|
600
|
+
return SSL_TLSEXT_ERR_OK;
|
601
|
+
}
|
602
|
+
|
603
|
+
static int
|
604
|
+
ssl_npn_select_cb(SSL *s, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg)
|
605
|
+
{
|
606
|
+
int i = 0;
|
607
|
+
VALUE sslctx_obj, cb, protocols, selected;
|
608
|
+
|
609
|
+
sslctx_obj = (VALUE) arg;
|
610
|
+
cb = rb_iv_get(sslctx_obj, "@npn_select_cb");
|
611
|
+
protocols = rb_ary_new();
|
612
|
+
|
613
|
+
/* The format is len_1|proto_1|...|len_n|proto_n\0 */
|
614
|
+
while (in[i]) {
|
615
|
+
VALUE protocol = rb_str_new((const char *) &in[i + 1], in[i]);
|
616
|
+
rb_ary_push(protocols, protocol);
|
617
|
+
i += in[i] + 1;
|
618
|
+
}
|
619
|
+
|
620
|
+
selected = rb_funcall(cb, rb_intern("call"), 1, protocols);
|
621
|
+
StringValue(selected);
|
622
|
+
*out = (unsigned char *) StringValuePtr(selected);
|
623
|
+
*outlen = RSTRING_LENINT(selected);
|
624
|
+
|
625
|
+
return SSL_TLSEXT_ERR_OK;
|
626
|
+
}
|
627
|
+
#endif
|
628
|
+
|
629
|
+
/* This function may serve as the entry point to support further
|
630
|
+
* callbacks. */
|
631
|
+
static void
|
632
|
+
ssl_info_cb(const SSL *ssl, int where, int val)
|
633
|
+
{
|
634
|
+
int state = SSL_state(ssl);
|
635
|
+
|
636
|
+
if ((where & SSL_CB_HANDSHAKE_START) &&
|
637
|
+
(state & SSL_ST_ACCEPT)) {
|
638
|
+
ssl_renegotiation_cb(ssl);
|
639
|
+
}
|
640
|
+
}
|
641
|
+
|
451
642
|
/*
|
452
643
|
* call-seq:
|
453
644
|
* ctx.setup => Qtrue # first time
|
454
645
|
* ctx.setup => nil # thereafter
|
455
646
|
*
|
456
647
|
* This method is called automatically when a new SSLSocket is created.
|
457
|
-
* Normally you do not need to call this method (unless you are writing an
|
648
|
+
* Normally you do not need to call this method (unless you are writing an
|
649
|
+
* extension in C).
|
458
650
|
*/
|
459
651
|
static VALUE
|
460
652
|
ossl_sslctx_setup(VALUE self)
|
@@ -506,14 +698,14 @@ ossl_sslctx_setup(VALUE self)
|
|
506
698
|
if (cert && key) {
|
507
699
|
if (!SSL_CTX_use_certificate(ctx, cert)) {
|
508
700
|
/* Adds a ref => Safe to FREE */
|
509
|
-
ossl_raise(eSSLError, "SSL_CTX_use_certificate
|
701
|
+
ossl_raise(eSSLError, "SSL_CTX_use_certificate");
|
510
702
|
}
|
511
703
|
if (!SSL_CTX_use_PrivateKey(ctx, key)) {
|
512
704
|
/* Adds a ref => Safe to FREE */
|
513
|
-
ossl_raise(eSSLError, "SSL_CTX_use_PrivateKey
|
705
|
+
ossl_raise(eSSLError, "SSL_CTX_use_PrivateKey");
|
514
706
|
}
|
515
707
|
if (!SSL_CTX_check_private_key(ctx)) {
|
516
|
-
ossl_raise(eSSLError, "SSL_CTX_check_private_key
|
708
|
+
ossl_raise(eSSLError, "SSL_CTX_check_private_key");
|
517
709
|
}
|
518
710
|
}
|
519
711
|
|
@@ -556,22 +748,36 @@ ossl_sslctx_setup(VALUE self)
|
|
556
748
|
if(!NIL_P(val)) SSL_CTX_set_timeout(ctx, NUM2LONG(val));
|
557
749
|
|
558
750
|
val = ossl_sslctx_get_verify_dep(self);
|
559
|
-
if(!NIL_P(val)) SSL_CTX_set_verify_depth(ctx,
|
751
|
+
if(!NIL_P(val)) SSL_CTX_set_verify_depth(ctx, NUM2INT(val));
|
560
752
|
|
561
753
|
val = ossl_sslctx_get_options(self);
|
562
754
|
if(!NIL_P(val)) {
|
563
|
-
|
755
|
+
SSL_CTX_set_options(ctx, NUM2LONG(val));
|
564
756
|
} else {
|
565
|
-
|
757
|
+
SSL_CTX_set_options(ctx, SSL_OP_ALL);
|
566
758
|
}
|
759
|
+
|
760
|
+
#ifdef HAVE_OPENSSL_NPN_NEGOTIATED
|
761
|
+
val = rb_iv_get(self, "@npn_protocols");
|
762
|
+
if (!NIL_P(val)) {
|
763
|
+
ssl_npn_encode_protocols(self, val);
|
764
|
+
SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_npn_advertise_cb, (void *) self);
|
765
|
+
OSSL_Debug("SSL NPN advertise callback added");
|
766
|
+
}
|
767
|
+
if (RTEST(rb_iv_get(self, "@npn_select_cb"))) {
|
768
|
+
SSL_CTX_set_next_proto_select_cb(ctx, ssl_npn_select_cb, (void *) self);
|
769
|
+
OSSL_Debug("SSL NPN select callback added");
|
770
|
+
}
|
771
|
+
#endif
|
772
|
+
|
567
773
|
rb_obj_freeze(self);
|
568
774
|
|
569
775
|
val = ossl_sslctx_get_sess_id_ctx(self);
|
570
776
|
if (!NIL_P(val)){
|
571
777
|
StringValue(val);
|
572
|
-
if (!SSL_CTX_set_session_id_context(ctx, RSTRING_PTR(val),
|
573
|
-
|
574
|
-
ossl_raise(eSSLError, "SSL_CTX_set_session_id_context
|
778
|
+
if (!SSL_CTX_set_session_id_context(ctx, (unsigned char *)RSTRING_PTR(val),
|
779
|
+
RSTRING_LENINT(val))){
|
780
|
+
ossl_raise(eSSLError, "SSL_CTX_set_session_id_context");
|
575
781
|
}
|
576
782
|
}
|
577
783
|
|
@@ -587,6 +793,15 @@ ossl_sslctx_setup(VALUE self)
|
|
587
793
|
SSL_CTX_sess_set_remove_cb(ctx, ossl_sslctx_session_remove_cb);
|
588
794
|
OSSL_Debug("SSL SESSION remove callback added");
|
589
795
|
}
|
796
|
+
|
797
|
+
#ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME
|
798
|
+
val = rb_iv_get(self, "@servername_cb");
|
799
|
+
if (!NIL_P(val)) {
|
800
|
+
SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb);
|
801
|
+
OSSL_Debug("SSL TLSEXT servername callback added");
|
802
|
+
}
|
803
|
+
#endif
|
804
|
+
|
590
805
|
return Qtrue;
|
591
806
|
}
|
592
807
|
|
@@ -609,6 +824,8 @@ ossl_ssl_cipher_to_ary(SSL_CIPHER *cipher)
|
|
609
824
|
/*
|
610
825
|
* call-seq:
|
611
826
|
* ctx.ciphers => [[name, version, bits, alg_bits], ...]
|
827
|
+
*
|
828
|
+
* The list of ciphers configured for this context.
|
612
829
|
*/
|
613
830
|
static VALUE
|
614
831
|
ossl_sslctx_get_ciphers(VALUE self)
|
@@ -629,10 +846,10 @@ ossl_sslctx_get_ciphers(VALUE self)
|
|
629
846
|
if (!ciphers)
|
630
847
|
return rb_ary_new();
|
631
848
|
|
632
|
-
num =
|
849
|
+
num = sk_SSL_CIPHER_num(ciphers);
|
633
850
|
ary = rb_ary_new2(num);
|
634
851
|
for(i = 0; i < num; i++){
|
635
|
-
cipher = (
|
852
|
+
cipher = sk_SSL_CIPHER_value(ciphers, i);
|
636
853
|
rb_ary_push(ary, ossl_ssl_cipher_to_ary(cipher));
|
637
854
|
}
|
638
855
|
return ary;
|
@@ -643,6 +860,12 @@ ossl_sslctx_get_ciphers(VALUE self)
|
|
643
860
|
* ctx.ciphers = "cipher1:cipher2:..."
|
644
861
|
* ctx.ciphers = [name, ...]
|
645
862
|
* ctx.ciphers = [[name, version, bits, alg_bits], ...]
|
863
|
+
*
|
864
|
+
* Sets the list of available ciphers for this context. Note in a server
|
865
|
+
* context some ciphers require the appropriate certificates. For example, an
|
866
|
+
* RSA cipher can only be chosen when an RSA certificate is available.
|
867
|
+
*
|
868
|
+
* See also OpenSSL::Cipher and OpenSSL::Cipher::ciphers
|
646
869
|
*/
|
647
870
|
static VALUE
|
648
871
|
ossl_sslctx_set_ciphers(VALUE self, VALUE v)
|
@@ -674,17 +897,17 @@ ossl_sslctx_set_ciphers(VALUE self, VALUE v)
|
|
674
897
|
return Qnil;
|
675
898
|
}
|
676
899
|
if (!SSL_CTX_set_cipher_list(ctx, RSTRING_PTR(str))) {
|
677
|
-
ossl_raise(eSSLError, "SSL_CTX_set_cipher_list
|
900
|
+
ossl_raise(eSSLError, "SSL_CTX_set_cipher_list");
|
678
901
|
}
|
679
902
|
|
680
903
|
return v;
|
681
904
|
}
|
682
905
|
|
683
|
-
|
684
906
|
/*
|
685
907
|
* call-seq:
|
686
908
|
* ctx.session_add(session) -> true | false
|
687
909
|
*
|
910
|
+
* Adds +session+ to the session cache
|
688
911
|
*/
|
689
912
|
static VALUE
|
690
913
|
ossl_sslctx_session_add(VALUE self, VALUE arg)
|
@@ -702,6 +925,7 @@ ossl_sslctx_session_add(VALUE self, VALUE arg)
|
|
702
925
|
* call-seq:
|
703
926
|
* ctx.session_remove(session) -> true | false
|
704
927
|
*
|
928
|
+
* Removes +session+ from the session cache
|
705
929
|
*/
|
706
930
|
static VALUE
|
707
931
|
ossl_sslctx_session_remove(VALUE self, VALUE arg)
|
@@ -717,8 +941,9 @@ ossl_sslctx_session_remove(VALUE self, VALUE arg)
|
|
717
941
|
|
718
942
|
/*
|
719
943
|
* call-seq:
|
720
|
-
* ctx.session_cache_mode ->
|
944
|
+
* ctx.session_cache_mode -> Integer
|
721
945
|
*
|
946
|
+
* The current session cache mode.
|
722
947
|
*/
|
723
948
|
static VALUE
|
724
949
|
ossl_sslctx_get_session_cache_mode(VALUE self)
|
@@ -732,8 +957,11 @@ ossl_sslctx_get_session_cache_mode(VALUE self)
|
|
732
957
|
|
733
958
|
/*
|
734
959
|
* call-seq:
|
735
|
-
* ctx.session_cache_mode=(integer) ->
|
960
|
+
* ctx.session_cache_mode=(integer) -> Integer
|
736
961
|
*
|
962
|
+
* Sets the SSL session cache mode. Bitwise-or together the desired
|
963
|
+
* SESSION_CACHE_* constants to set. See SSL_CTX_set_session_cache_mode(3) for
|
964
|
+
* details.
|
737
965
|
*/
|
738
966
|
static VALUE
|
739
967
|
ossl_sslctx_set_session_cache_mode(VALUE self, VALUE arg)
|
@@ -749,8 +977,10 @@ ossl_sslctx_set_session_cache_mode(VALUE self, VALUE arg)
|
|
749
977
|
|
750
978
|
/*
|
751
979
|
* call-seq:
|
752
|
-
* ctx.session_cache_size ->
|
980
|
+
* ctx.session_cache_size -> Integer
|
753
981
|
*
|
982
|
+
* Returns the current session cache size. Zero is used to represent an
|
983
|
+
* unlimited cache size.
|
754
984
|
*/
|
755
985
|
static VALUE
|
756
986
|
ossl_sslctx_get_session_cache_size(VALUE self)
|
@@ -764,8 +994,10 @@ ossl_sslctx_get_session_cache_size(VALUE self)
|
|
764
994
|
|
765
995
|
/*
|
766
996
|
* call-seq:
|
767
|
-
* ctx.session_cache_size=(integer) ->
|
997
|
+
* ctx.session_cache_size=(integer) -> Integer
|
768
998
|
*
|
999
|
+
* Sets the session cache size. Returns the previously valid session cache
|
1000
|
+
* size. Zero is used to represent an unlimited session cache size.
|
769
1001
|
*/
|
770
1002
|
static VALUE
|
771
1003
|
ossl_sslctx_set_session_cache_size(VALUE self, VALUE arg)
|
@@ -783,6 +1015,23 @@ ossl_sslctx_set_session_cache_size(VALUE self, VALUE arg)
|
|
783
1015
|
* call-seq:
|
784
1016
|
* ctx.session_cache_stats -> Hash
|
785
1017
|
*
|
1018
|
+
* Returns a Hash containing the following keys:
|
1019
|
+
*
|
1020
|
+
* :accept:: Number of started SSL/TLS handshakes in server mode
|
1021
|
+
* :accept_good:: Number of established SSL/TLS sessions in server mode
|
1022
|
+
* :accept_renegotiate:: Number of start renegotiations in server mode
|
1023
|
+
* :cache_full:: Number of sessions that were removed due to cache overflow
|
1024
|
+
* :cache_hits:: Number of successfully reused connections
|
1025
|
+
* :cache_misses:: Number of sessions proposed by clients that were not found
|
1026
|
+
* in the cache
|
1027
|
+
* :cache_num:: Number of sessions in the internal session cache
|
1028
|
+
* :cb_hits:: Number of sessions retrieved from the external cache in server
|
1029
|
+
* mode
|
1030
|
+
* :connect:: Number of started SSL/TLS handshakes in client mode
|
1031
|
+
* :connect_good:: Number of established SSL/TLS sessions in client mode
|
1032
|
+
* :connect_renegotiate:: Number of start renegotiations in client mode
|
1033
|
+
* :timeouts:: Number of sessions proposed by clients that were found in the
|
1034
|
+
* cache but had expired due to timeouts
|
786
1035
|
*/
|
787
1036
|
static VALUE
|
788
1037
|
ossl_sslctx_get_session_cache_stats(VALUE self)
|
@@ -814,6 +1063,7 @@ ossl_sslctx_get_session_cache_stats(VALUE self)
|
|
814
1063
|
* call-seq:
|
815
1064
|
* ctx.flush_sessions(time | nil) -> self
|
816
1065
|
*
|
1066
|
+
* Removes sessions in the internal cache that have expired at +time+.
|
817
1067
|
*/
|
818
1068
|
static VALUE
|
819
1069
|
ossl_sslctx_flush_sessions(int argc, VALUE *argv, VALUE self)
|
@@ -821,7 +1071,6 @@ ossl_sslctx_flush_sessions(int argc, VALUE *argv, VALUE self)
|
|
821
1071
|
VALUE arg1;
|
822
1072
|
SSL_CTX *ctx;
|
823
1073
|
time_t tm = 0;
|
824
|
-
int cb_state;
|
825
1074
|
|
826
1075
|
rb_scan_args(argc, argv, "01", &arg1);
|
827
1076
|
|
@@ -832,7 +1081,7 @@ ossl_sslctx_flush_sessions(int argc, VALUE *argv, VALUE self)
|
|
832
1081
|
} else if (rb_obj_is_instance_of(arg1, rb_cTime)) {
|
833
1082
|
tm = NUM2LONG(rb_funcall(arg1, rb_intern("to_i"), 0));
|
834
1083
|
} else {
|
835
|
-
|
1084
|
+
ossl_raise(rb_eArgError, "arg must be Time or nil");
|
836
1085
|
}
|
837
1086
|
|
838
1087
|
SSL_CTX_flush_sessions(ctx, (long)tm);
|
@@ -846,16 +1095,27 @@ ossl_sslctx_flush_sessions(int argc, VALUE *argv, VALUE self)
|
|
846
1095
|
static void
|
847
1096
|
ossl_ssl_shutdown(SSL *ssl)
|
848
1097
|
{
|
1098
|
+
int i, rc;
|
1099
|
+
|
849
1100
|
if (ssl) {
|
850
|
-
|
851
|
-
|
1101
|
+
/* 4 is from SSL_smart_shutdown() of mod_ssl.c (v2.2.19) */
|
1102
|
+
/* It says max 2x pending + 2x data = 4 */
|
1103
|
+
for (i = 0; i < 4; ++i) {
|
1104
|
+
/*
|
1105
|
+
* Ignore the case SSL_shutdown returns -1. Empty handshake_func
|
1106
|
+
* must not happen.
|
1107
|
+
*/
|
1108
|
+
if (rc = SSL_shutdown(ssl))
|
1109
|
+
break;
|
1110
|
+
}
|
1111
|
+
SSL_clear(ssl);
|
1112
|
+
ERR_clear_error();
|
852
1113
|
}
|
853
1114
|
}
|
854
1115
|
|
855
1116
|
static void
|
856
1117
|
ossl_ssl_free(SSL *ssl)
|
857
1118
|
{
|
858
|
-
ossl_ssl_shutdown(ssl);
|
859
1119
|
SSL_free(ssl);
|
860
1120
|
}
|
861
1121
|
|
@@ -870,9 +1130,11 @@ ossl_ssl_s_alloc(VALUE klass)
|
|
870
1130
|
* SSLSocket.new(io) => aSSLSocket
|
871
1131
|
* SSLSocket.new(io, ctx) => aSSLSocket
|
872
1132
|
*
|
873
|
-
*
|
874
|
-
*
|
875
|
-
*
|
1133
|
+
* Creates a new SSL socket from +io+ which must be a real ruby object (not an
|
1134
|
+
* IO-like object that responds to read/write.
|
1135
|
+
*
|
1136
|
+
* If +ctx+ is provided the SSL Sockets initial params will be taken from
|
1137
|
+
* the context.
|
876
1138
|
*
|
877
1139
|
* The OpenSSL::Buffering module provides additional IO methods.
|
878
1140
|
*
|
@@ -893,6 +1155,9 @@ ossl_ssl_initialize(int argc, VALUE *argv, VALUE self)
|
|
893
1155
|
ossl_ssl_set_ctx(self, ctx);
|
894
1156
|
ossl_ssl_set_sync_close(self, Qfalse);
|
895
1157
|
ossl_sslctx_setup(ctx);
|
1158
|
+
|
1159
|
+
rb_iv_set(self, "@hostname", Qnil);
|
1160
|
+
|
896
1161
|
rb_call_super(0, 0);
|
897
1162
|
|
898
1163
|
return self;
|
@@ -908,15 +1173,25 @@ ossl_ssl_setup(VALUE self)
|
|
908
1173
|
|
909
1174
|
Data_Get_Struct(self, SSL, ssl);
|
910
1175
|
if(!ssl){
|
1176
|
+
#ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME
|
1177
|
+
VALUE hostname = rb_iv_get(self, "@hostname");
|
1178
|
+
#endif
|
1179
|
+
|
911
1180
|
v_ctx = ossl_ssl_get_ctx(self);
|
912
1181
|
Data_Get_Struct(v_ctx, SSL_CTX, ctx);
|
913
1182
|
|
914
1183
|
ssl = SSL_new(ctx);
|
915
1184
|
if (!ssl) {
|
916
|
-
ossl_raise(eSSLError, "SSL_new
|
1185
|
+
ossl_raise(eSSLError, "SSL_new");
|
917
1186
|
}
|
918
1187
|
DATA_PTR(self) = ssl;
|
919
1188
|
|
1189
|
+
#ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME
|
1190
|
+
if (!NIL_P(hostname)) {
|
1191
|
+
if (SSL_set_tlsext_host_name(ssl, StringValuePtr(hostname)) != 1)
|
1192
|
+
ossl_raise(eSSLError, "SSL_set_tlsext_host_name");
|
1193
|
+
}
|
1194
|
+
#endif
|
920
1195
|
io = ossl_ssl_get_io(self);
|
921
1196
|
GetOpenFile(io, fptr);
|
922
1197
|
rb_io_check_readable(fptr);
|
@@ -929,19 +1204,49 @@ ossl_ssl_setup(VALUE self)
|
|
929
1204
|
SSL_set_ex_data(ssl, ossl_ssl_ex_client_cert_cb_idx, (void*)cb);
|
930
1205
|
cb = ossl_sslctx_get_tmp_dh_cb(v_ctx);
|
931
1206
|
SSL_set_ex_data(ssl, ossl_ssl_ex_tmp_dh_callback_idx, (void*)cb);
|
1207
|
+
SSL_set_info_callback(ssl, ssl_info_cb);
|
932
1208
|
}
|
933
1209
|
|
934
1210
|
return Qtrue;
|
935
1211
|
}
|
936
1212
|
|
937
1213
|
#ifdef _WIN32
|
938
|
-
#define ssl_get_error(ssl, ret) (errno = WSAGetLastError(), SSL_get_error(ssl, ret))
|
1214
|
+
#define ssl_get_error(ssl, ret) (errno = rb_w32_map_errno(WSAGetLastError()), SSL_get_error((ssl), (ret)))
|
939
1215
|
#else
|
940
|
-
#define ssl_get_error(ssl, ret) SSL_get_error(ssl, ret)
|
1216
|
+
#define ssl_get_error(ssl, ret) SSL_get_error((ssl), (ret))
|
941
1217
|
#endif
|
942
1218
|
|
1219
|
+
#define ossl_ssl_data_get_struct(v, ssl) \
|
1220
|
+
do { \
|
1221
|
+
Data_Get_Struct((v), SSL, (ssl)); \
|
1222
|
+
if (!(ssl)) { \
|
1223
|
+
rb_warning("SSL session is not started yet."); \
|
1224
|
+
return Qnil; \
|
1225
|
+
} \
|
1226
|
+
} while (0)
|
1227
|
+
|
1228
|
+
static void
|
1229
|
+
write_would_block(int nonblock)
|
1230
|
+
{
|
1231
|
+
if (nonblock) {
|
1232
|
+
VALUE exc = ossl_exc_new(eSSLError, "write would block");
|
1233
|
+
rb_extend_object(exc, rb_mWaitWritable);
|
1234
|
+
rb_exc_raise(exc);
|
1235
|
+
}
|
1236
|
+
}
|
1237
|
+
|
1238
|
+
static void
|
1239
|
+
read_would_block(int nonblock)
|
1240
|
+
{
|
1241
|
+
if (nonblock) {
|
1242
|
+
VALUE exc = ossl_exc_new(eSSLError, "read would block");
|
1243
|
+
rb_extend_object(exc, rb_mWaitReadable);
|
1244
|
+
rb_exc_raise(exc);
|
1245
|
+
}
|
1246
|
+
}
|
1247
|
+
|
943
1248
|
static VALUE
|
944
|
-
ossl_start_ssl(VALUE self, int (*func)(), const char *funcname)
|
1249
|
+
ossl_start_ssl(VALUE self, int (*func)(), const char *funcname, int nonblock)
|
945
1250
|
{
|
946
1251
|
SSL *ssl;
|
947
1252
|
rb_io_t *fptr;
|
@@ -950,15 +1255,26 @@ ossl_start_ssl(VALUE self, int (*func)(), const char *funcname)
|
|
950
1255
|
|
951
1256
|
rb_ivar_set(self, ID_callback_state, Qnil);
|
952
1257
|
|
953
|
-
|
1258
|
+
ossl_ssl_data_get_struct(self, ssl);
|
1259
|
+
|
954
1260
|
GetOpenFile(ossl_ssl_get_io(self), fptr);
|
955
1261
|
for(;;){
|
956
|
-
|
1262
|
+
ret = func(ssl);
|
1263
|
+
|
1264
|
+
cb_state = rb_ivar_get(self, ID_callback_state);
|
1265
|
+
if (!NIL_P(cb_state))
|
1266
|
+
rb_jump_tag(NUM2INT(cb_state));
|
1267
|
+
|
1268
|
+
if (ret > 0)
|
1269
|
+
break;
|
1270
|
+
|
957
1271
|
switch((ret2 = ssl_get_error(ssl, ret))){
|
958
1272
|
case SSL_ERROR_WANT_WRITE:
|
1273
|
+
write_would_block(nonblock);
|
959
1274
|
rb_io_wait_writable(FPTR_TO_FD(fptr));
|
960
1275
|
continue;
|
961
1276
|
case SSL_ERROR_WANT_READ:
|
1277
|
+
read_would_block(nonblock);
|
962
1278
|
rb_io_wait_readable(FPTR_TO_FD(fptr));
|
963
1279
|
continue;
|
964
1280
|
case SSL_ERROR_SYSCALL:
|
@@ -969,46 +1285,89 @@ ossl_start_ssl(VALUE self, int (*func)(), const char *funcname)
|
|
969
1285
|
}
|
970
1286
|
}
|
971
1287
|
|
972
|
-
cb_state = rb_ivar_get(self, ID_callback_state);
|
973
|
-
if (!NIL_P(cb_state))
|
974
|
-
rb_jump_tag(NUM2INT(cb_state));
|
975
|
-
|
976
1288
|
return self;
|
977
1289
|
}
|
978
1290
|
|
979
1291
|
/*
|
980
1292
|
* call-seq:
|
981
1293
|
* ssl.connect => self
|
1294
|
+
*
|
1295
|
+
* Initiates an SSL/TLS handshake with a server. The handshake may be started
|
1296
|
+
* after unencrypted data has been sent over the socket.
|
982
1297
|
*/
|
983
1298
|
static VALUE
|
984
1299
|
ossl_ssl_connect(VALUE self)
|
985
1300
|
{
|
986
1301
|
ossl_ssl_setup(self);
|
987
|
-
return ossl_start_ssl(self, SSL_connect, "SSL_connect");
|
1302
|
+
return ossl_start_ssl(self, SSL_connect, "SSL_connect", 0);
|
1303
|
+
}
|
1304
|
+
|
1305
|
+
/*
|
1306
|
+
* call-seq:
|
1307
|
+
* ssl.connect_nonblock => self
|
1308
|
+
*
|
1309
|
+
* Initiates the SSL/TLS handshake as a client in non-blocking manner.
|
1310
|
+
*
|
1311
|
+
* # emulates blocking connect
|
1312
|
+
* begin
|
1313
|
+
* ssl.connect_nonblock
|
1314
|
+
* rescue IO::WaitReadable
|
1315
|
+
* IO.select([s2])
|
1316
|
+
* retry
|
1317
|
+
* rescue IO::WaitWritable
|
1318
|
+
* IO.select(nil, [s2])
|
1319
|
+
* retry
|
1320
|
+
* end
|
1321
|
+
*
|
1322
|
+
*/
|
1323
|
+
static VALUE
|
1324
|
+
ossl_ssl_connect_nonblock(VALUE self)
|
1325
|
+
{
|
1326
|
+
ossl_ssl_setup(self);
|
1327
|
+
return ossl_start_ssl(self, SSL_connect, "SSL_connect", 1);
|
988
1328
|
}
|
989
1329
|
|
990
1330
|
/*
|
991
1331
|
* call-seq:
|
992
1332
|
* ssl.accept => self
|
1333
|
+
*
|
1334
|
+
* Waits for a SSL/TLS client to initiate a handshake. The handshake may be
|
1335
|
+
* started after unencrypted data has been sent over the socket.
|
993
1336
|
*/
|
994
1337
|
static VALUE
|
995
1338
|
ossl_ssl_accept(VALUE self)
|
996
1339
|
{
|
997
1340
|
ossl_ssl_setup(self);
|
998
|
-
return ossl_start_ssl(self, SSL_accept, "SSL_accept");
|
1341
|
+
return ossl_start_ssl(self, SSL_accept, "SSL_accept", 0);
|
999
1342
|
}
|
1000
1343
|
|
1001
1344
|
/*
|
1002
1345
|
* call-seq:
|
1003
|
-
* ssl.
|
1004
|
-
*
|
1346
|
+
* ssl.accept_nonblock => self
|
1347
|
+
*
|
1348
|
+
* Initiates the SSL/TLS handshake as a server in non-blocking manner.
|
1349
|
+
*
|
1350
|
+
* # emulates blocking accept
|
1351
|
+
* begin
|
1352
|
+
* ssl.accept_nonblock
|
1353
|
+
* rescue IO::WaitReadable
|
1354
|
+
* IO.select([s2])
|
1355
|
+
* retry
|
1356
|
+
* rescue IO::WaitWritable
|
1357
|
+
* IO.select(nil, [s2])
|
1358
|
+
* retry
|
1359
|
+
* end
|
1005
1360
|
*
|
1006
|
-
* === Parameters
|
1007
|
-
* * +length+ is a positive integer.
|
1008
|
-
* * +buffer+ is a string used to store the result.
|
1009
1361
|
*/
|
1010
1362
|
static VALUE
|
1011
|
-
|
1363
|
+
ossl_ssl_accept_nonblock(VALUE self)
|
1364
|
+
{
|
1365
|
+
ossl_ssl_setup(self);
|
1366
|
+
return ossl_start_ssl(self, SSL_accept, "SSL_accept", 1);
|
1367
|
+
}
|
1368
|
+
|
1369
|
+
static VALUE
|
1370
|
+
ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
|
1012
1371
|
{
|
1013
1372
|
SSL *ssl;
|
1014
1373
|
int ilen, nread = 0;
|
@@ -1028,33 +1387,35 @@ ossl_ssl_read(int argc, VALUE *argv, VALUE self)
|
|
1028
1387
|
Data_Get_Struct(self, SSL, ssl);
|
1029
1388
|
GetOpenFile(ossl_ssl_get_io(self), fptr);
|
1030
1389
|
if (ssl) {
|
1031
|
-
if(SSL_pending(ssl) <= 0)
|
1390
|
+
if(!nonblock && SSL_pending(ssl) <= 0)
|
1032
1391
|
rb_thread_wait_fd(FPTR_TO_FD(fptr));
|
1033
1392
|
for (;;){
|
1034
|
-
nread = SSL_read(ssl, RSTRING_PTR(str),
|
1393
|
+
nread = SSL_read(ssl, RSTRING_PTR(str), RSTRING_LENINT(str));
|
1035
1394
|
switch(ssl_get_error(ssl, nread)){
|
1036
1395
|
case SSL_ERROR_NONE:
|
1037
1396
|
goto end;
|
1038
1397
|
case SSL_ERROR_ZERO_RETURN:
|
1039
1398
|
rb_eof_error();
|
1040
1399
|
case SSL_ERROR_WANT_WRITE:
|
1400
|
+
write_would_block(nonblock);
|
1041
1401
|
rb_io_wait_writable(FPTR_TO_FD(fptr));
|
1042
1402
|
continue;
|
1043
1403
|
case SSL_ERROR_WANT_READ:
|
1404
|
+
read_would_block(nonblock);
|
1044
1405
|
rb_io_wait_readable(FPTR_TO_FD(fptr));
|
1045
1406
|
continue;
|
1046
1407
|
case SSL_ERROR_SYSCALL:
|
1047
1408
|
if(ERR_peek_error() == 0 && nread == 0) rb_eof_error();
|
1048
1409
|
rb_sys_fail(0);
|
1049
1410
|
default:
|
1050
|
-
ossl_raise(eSSLError, "SSL_read
|
1411
|
+
ossl_raise(eSSLError, "SSL_read");
|
1051
1412
|
}
|
1052
1413
|
}
|
1053
1414
|
}
|
1054
1415
|
else {
|
1055
|
-
ID
|
1416
|
+
ID meth = nonblock ? rb_intern("read_nonblock") : rb_intern("sysread");
|
1056
1417
|
rb_warning("SSL session is not started yet.");
|
1057
|
-
return rb_funcall(ossl_ssl_get_io(self),
|
1418
|
+
return rb_funcall(ossl_ssl_get_io(self), meth, 2, len, str);
|
1058
1419
|
}
|
1059
1420
|
|
1060
1421
|
end:
|
@@ -1066,10 +1427,37 @@ ossl_ssl_read(int argc, VALUE *argv, VALUE self)
|
|
1066
1427
|
|
1067
1428
|
/*
|
1068
1429
|
* call-seq:
|
1069
|
-
* ssl.
|
1430
|
+
* ssl.sysread(length) => string
|
1431
|
+
* ssl.sysread(length, buffer) => buffer
|
1432
|
+
*
|
1433
|
+
* Reads +length+ bytes from the SSL connection. If a pre-allocated +buffer+
|
1434
|
+
* is provided the data will be written into it.
|
1070
1435
|
*/
|
1071
1436
|
static VALUE
|
1072
|
-
|
1437
|
+
ossl_ssl_read(int argc, VALUE *argv, VALUE self)
|
1438
|
+
{
|
1439
|
+
return ossl_ssl_read_internal(argc, argv, self, 0);
|
1440
|
+
}
|
1441
|
+
|
1442
|
+
/*
|
1443
|
+
* call-seq:
|
1444
|
+
* ssl.sysread_nonblock(length) => string
|
1445
|
+
* ssl.sysread_nonblock(length, buffer) => buffer
|
1446
|
+
*
|
1447
|
+
* A non-blocking version of #sysread. Raises an SSLError if reading would
|
1448
|
+
* block.
|
1449
|
+
*
|
1450
|
+
* Reads +length+ bytes from the SSL connection. If a pre-allocated +buffer+
|
1451
|
+
* is provided the data will be written into it.
|
1452
|
+
*/
|
1453
|
+
static VALUE
|
1454
|
+
ossl_ssl_read_nonblock(int argc, VALUE *argv, VALUE self)
|
1455
|
+
{
|
1456
|
+
return ossl_ssl_read_internal(argc, argv, self, 1);
|
1457
|
+
}
|
1458
|
+
|
1459
|
+
static VALUE
|
1460
|
+
ossl_ssl_write_internal(VALUE self, VALUE str, int nonblock)
|
1073
1461
|
{
|
1074
1462
|
SSL *ssl;
|
1075
1463
|
int nwrite = 0;
|
@@ -1081,20 +1469,22 @@ ossl_ssl_write(VALUE self, VALUE str)
|
|
1081
1469
|
|
1082
1470
|
if (ssl) {
|
1083
1471
|
for (;;){
|
1084
|
-
nwrite = SSL_write(ssl, RSTRING_PTR(str),
|
1472
|
+
nwrite = SSL_write(ssl, RSTRING_PTR(str), RSTRING_LENINT(str));
|
1085
1473
|
switch(ssl_get_error(ssl, nwrite)){
|
1086
1474
|
case SSL_ERROR_NONE:
|
1087
1475
|
goto end;
|
1088
1476
|
case SSL_ERROR_WANT_WRITE:
|
1477
|
+
write_would_block(nonblock);
|
1089
1478
|
rb_io_wait_writable(FPTR_TO_FD(fptr));
|
1090
1479
|
continue;
|
1091
1480
|
case SSL_ERROR_WANT_READ:
|
1481
|
+
read_would_block(nonblock);
|
1092
1482
|
rb_io_wait_readable(FPTR_TO_FD(fptr));
|
1093
1483
|
continue;
|
1094
1484
|
case SSL_ERROR_SYSCALL:
|
1095
1485
|
if (errno) rb_sys_fail(0);
|
1096
1486
|
default:
|
1097
|
-
ossl_raise(eSSLError, "SSL_write
|
1487
|
+
ossl_raise(eSSLError, "SSL_write");
|
1098
1488
|
}
|
1099
1489
|
}
|
1100
1490
|
}
|
@@ -1108,19 +1498,54 @@ ossl_ssl_write(VALUE self, VALUE str)
|
|
1108
1498
|
return INT2NUM(nwrite);
|
1109
1499
|
}
|
1110
1500
|
|
1501
|
+
/*
|
1502
|
+
* call-seq:
|
1503
|
+
* ssl.syswrite(string) => Integer
|
1504
|
+
*
|
1505
|
+
* Writes +string+ to the SSL connection.
|
1506
|
+
*/
|
1507
|
+
static VALUE
|
1508
|
+
ossl_ssl_write(VALUE self, VALUE str)
|
1509
|
+
{
|
1510
|
+
return ossl_ssl_write_internal(self, str, 0);
|
1511
|
+
}
|
1512
|
+
|
1513
|
+
/*
|
1514
|
+
* call-seq:
|
1515
|
+
* ssl.syswrite_nonblock(string) => Integer
|
1516
|
+
*
|
1517
|
+
* Writes +string+ to the SSL connection in a non-blocking manner. Raises an
|
1518
|
+
* SSLError if writing would block.
|
1519
|
+
*/
|
1520
|
+
static VALUE
|
1521
|
+
ossl_ssl_write_nonblock(VALUE self, VALUE str)
|
1522
|
+
{
|
1523
|
+
return ossl_ssl_write_internal(self, str, 1);
|
1524
|
+
}
|
1525
|
+
|
1111
1526
|
/*
|
1112
1527
|
* call-seq:
|
1113
1528
|
* ssl.sysclose => nil
|
1529
|
+
*
|
1530
|
+
* Shuts down the SSL connection and prepares it for another connection.
|
1114
1531
|
*/
|
1115
1532
|
static VALUE
|
1116
1533
|
ossl_ssl_close(VALUE self)
|
1117
1534
|
{
|
1118
1535
|
SSL *ssl;
|
1119
1536
|
|
1120
|
-
|
1121
|
-
|
1122
|
-
if (
|
1123
|
-
|
1537
|
+
ossl_ssl_data_get_struct(self, ssl);
|
1538
|
+
|
1539
|
+
if (ssl) {
|
1540
|
+
VALUE io = ossl_ssl_get_io(self);
|
1541
|
+
if (!RTEST(rb_funcall(io, rb_intern("closed?"), 0))) {
|
1542
|
+
ossl_ssl_shutdown(ssl);
|
1543
|
+
SSL_free(ssl);
|
1544
|
+
DATA_PTR(self) = NULL;
|
1545
|
+
if (RTEST(ossl_ssl_get_sync_close(self)))
|
1546
|
+
rb_funcall(io, rb_intern("close"), 0);
|
1547
|
+
}
|
1548
|
+
}
|
1124
1549
|
|
1125
1550
|
return Qnil;
|
1126
1551
|
}
|
@@ -1128,6 +1553,8 @@ ossl_ssl_close(VALUE self)
|
|
1128
1553
|
/*
|
1129
1554
|
* call-seq:
|
1130
1555
|
* ssl.cert => cert or nil
|
1556
|
+
*
|
1557
|
+
* The X509 certificate for this socket endpoint.
|
1131
1558
|
*/
|
1132
1559
|
static VALUE
|
1133
1560
|
ossl_ssl_get_cert(VALUE self)
|
@@ -1135,11 +1562,7 @@ ossl_ssl_get_cert(VALUE self)
|
|
1135
1562
|
SSL *ssl;
|
1136
1563
|
X509 *cert = NULL;
|
1137
1564
|
|
1138
|
-
|
1139
|
-
if (ssl) {
|
1140
|
-
rb_warning("SSL session is not started yet.");
|
1141
|
-
return Qnil;
|
1142
|
-
}
|
1565
|
+
ossl_ssl_data_get_struct(self, ssl);
|
1143
1566
|
|
1144
1567
|
/*
|
1145
1568
|
* Is this OpenSSL bug? Should add a ref?
|
@@ -1156,6 +1579,8 @@ ossl_ssl_get_cert(VALUE self)
|
|
1156
1579
|
/*
|
1157
1580
|
* call-seq:
|
1158
1581
|
* ssl.peer_cert => cert or nil
|
1582
|
+
*
|
1583
|
+
* The X509 certificate for this socket's peer.
|
1159
1584
|
*/
|
1160
1585
|
static VALUE
|
1161
1586
|
ossl_ssl_get_peer_cert(VALUE self)
|
@@ -1164,12 +1589,7 @@ ossl_ssl_get_peer_cert(VALUE self)
|
|
1164
1589
|
X509 *cert = NULL;
|
1165
1590
|
VALUE obj;
|
1166
1591
|
|
1167
|
-
|
1168
|
-
|
1169
|
-
if (!ssl){
|
1170
|
-
rb_warning("SSL session is not started yet.");
|
1171
|
-
return Qnil;
|
1172
|
-
}
|
1592
|
+
ossl_ssl_data_get_struct(self, ssl);
|
1173
1593
|
|
1174
1594
|
cert = SSL_get_peer_certificate(ssl); /* Adds a ref => Safe to FREE. */
|
1175
1595
|
|
@@ -1185,6 +1605,8 @@ ossl_ssl_get_peer_cert(VALUE self)
|
|
1185
1605
|
/*
|
1186
1606
|
* call-seq:
|
1187
1607
|
* ssl.peer_cert_chain => [cert, ...] or nil
|
1608
|
+
*
|
1609
|
+
* The X509 certificate chain for this socket's peer.
|
1188
1610
|
*/
|
1189
1611
|
static VALUE
|
1190
1612
|
ossl_ssl_get_peer_cert_chain(VALUE self)
|
@@ -1195,11 +1617,8 @@ ossl_ssl_get_peer_cert_chain(VALUE self)
|
|
1195
1617
|
VALUE ary;
|
1196
1618
|
int i, num;
|
1197
1619
|
|
1198
|
-
|
1199
|
-
|
1200
|
-
rb_warning("SSL session is not started yet.");
|
1201
|
-
return Qnil;
|
1202
|
-
}
|
1620
|
+
ossl_ssl_data_get_struct(self, ssl);
|
1621
|
+
|
1203
1622
|
chain = SSL_get_peer_cert_chain(ssl);
|
1204
1623
|
if(!chain) return Qnil;
|
1205
1624
|
num = sk_X509_num(chain);
|
@@ -1213,21 +1632,37 @@ ossl_ssl_get_peer_cert_chain(VALUE self)
|
|
1213
1632
|
}
|
1214
1633
|
|
1215
1634
|
/*
|
1216
|
-
|
1217
|
-
|
1218
|
-
|
1635
|
+
* call-seq:
|
1636
|
+
* ssl.version => String
|
1637
|
+
*
|
1638
|
+
* Returns a String representing the SSL/TLS version that was negotiated
|
1639
|
+
* for the connection, for example "TLSv1.2".
|
1640
|
+
*/
|
1641
|
+
static VALUE
|
1642
|
+
ossl_ssl_get_version(VALUE self)
|
1643
|
+
{
|
1644
|
+
SSL *ssl;
|
1645
|
+
|
1646
|
+
ossl_ssl_data_get_struct(self, ssl);
|
1647
|
+
|
1648
|
+
return rb_str_new2(SSL_get_version(ssl));
|
1649
|
+
}
|
1650
|
+
|
1651
|
+
/*
|
1652
|
+
* call-seq:
|
1653
|
+
* ssl.cipher => [name, version, bits, alg_bits]
|
1654
|
+
*
|
1655
|
+
* The cipher being used for the current connection
|
1656
|
+
*/
|
1219
1657
|
static VALUE
|
1220
1658
|
ossl_ssl_get_cipher(VALUE self)
|
1221
1659
|
{
|
1222
1660
|
SSL *ssl;
|
1223
1661
|
SSL_CIPHER *cipher;
|
1224
1662
|
|
1225
|
-
|
1226
|
-
|
1227
|
-
|
1228
|
-
return Qnil;
|
1229
|
-
}
|
1230
|
-
cipher = SSL_get_current_cipher(ssl);
|
1663
|
+
ossl_ssl_data_get_struct(self, ssl);
|
1664
|
+
|
1665
|
+
cipher = (SSL_CIPHER *)SSL_get_current_cipher(ssl);
|
1231
1666
|
|
1232
1667
|
return ossl_ssl_cipher_to_ary(cipher);
|
1233
1668
|
}
|
@@ -1235,6 +1670,8 @@ ossl_ssl_get_cipher(VALUE self)
|
|
1235
1670
|
/*
|
1236
1671
|
* call-seq:
|
1237
1672
|
* ssl.state => string
|
1673
|
+
*
|
1674
|
+
* A description of the current connection state.
|
1238
1675
|
*/
|
1239
1676
|
static VALUE
|
1240
1677
|
ossl_ssl_get_state(VALUE self)
|
@@ -1242,11 +1679,8 @@ ossl_ssl_get_state(VALUE self)
|
|
1242
1679
|
SSL *ssl;
|
1243
1680
|
VALUE ret;
|
1244
1681
|
|
1245
|
-
|
1246
|
-
|
1247
|
-
rb_warning("SSL session is not started yet.");
|
1248
|
-
return Qnil;
|
1249
|
-
}
|
1682
|
+
ossl_ssl_data_get_struct(self, ssl);
|
1683
|
+
|
1250
1684
|
ret = rb_str_new2(SSL_state_string(ssl));
|
1251
1685
|
if (ruby_verbose) {
|
1252
1686
|
rb_str_cat2(ret, ": ");
|
@@ -1257,49 +1691,47 @@ ossl_ssl_get_state(VALUE self)
|
|
1257
1691
|
|
1258
1692
|
/*
|
1259
1693
|
* call-seq:
|
1260
|
-
* ssl.pending =>
|
1694
|
+
* ssl.pending => Integer
|
1695
|
+
*
|
1696
|
+
* The number of bytes that are immediately available for reading
|
1261
1697
|
*/
|
1262
1698
|
static VALUE
|
1263
1699
|
ossl_ssl_pending(VALUE self)
|
1264
1700
|
{
|
1265
1701
|
SSL *ssl;
|
1266
1702
|
|
1267
|
-
|
1268
|
-
if (!ssl) {
|
1269
|
-
rb_warning("SSL session is not started yet.");
|
1270
|
-
return Qnil;
|
1271
|
-
}
|
1703
|
+
ossl_ssl_data_get_struct(self, ssl);
|
1272
1704
|
|
1273
1705
|
return INT2NUM(SSL_pending(ssl));
|
1274
1706
|
}
|
1275
1707
|
|
1276
1708
|
/*
|
1277
|
-
*
|
1278
|
-
*
|
1709
|
+
* call-seq:
|
1710
|
+
* ssl.session_reused? -> true | false
|
1279
1711
|
*
|
1712
|
+
* Returns true if a reused session was negotiated during the handshake.
|
1280
1713
|
*/
|
1281
1714
|
static VALUE
|
1282
1715
|
ossl_ssl_session_reused(VALUE self)
|
1283
1716
|
{
|
1284
1717
|
SSL *ssl;
|
1285
1718
|
|
1286
|
-
|
1287
|
-
if (!ssl) {
|
1288
|
-
rb_warning("SSL session is not started yet.");
|
1289
|
-
return Qnil;
|
1290
|
-
}
|
1719
|
+
ossl_ssl_data_get_struct(self, ssl);
|
1291
1720
|
|
1292
1721
|
switch(SSL_session_reused(ssl)) {
|
1293
1722
|
case 1: return Qtrue;
|
1294
1723
|
case 0: return Qfalse;
|
1295
1724
|
default: ossl_raise(eSSLError, "SSL_session_reused");
|
1296
1725
|
}
|
1726
|
+
|
1727
|
+
UNREACHABLE;
|
1297
1728
|
}
|
1298
1729
|
|
1299
1730
|
/*
|
1300
|
-
*
|
1301
|
-
*
|
1731
|
+
* call-seq:
|
1732
|
+
* ssl.session = session -> session
|
1302
1733
|
*
|
1734
|
+
* Sets the Session to be used when the connection is established.
|
1303
1735
|
*/
|
1304
1736
|
static VALUE
|
1305
1737
|
ossl_ssl_set_session(VALUE self, VALUE arg1)
|
@@ -1310,11 +1742,7 @@ ossl_ssl_set_session(VALUE self, VALUE arg1)
|
|
1310
1742
|
/* why is ossl_ssl_setup delayed? */
|
1311
1743
|
ossl_ssl_setup(self);
|
1312
1744
|
|
1313
|
-
|
1314
|
-
if (!ssl) {
|
1315
|
-
rb_warning("SSL session is not started yet.");
|
1316
|
-
return Qnil;
|
1317
|
-
}
|
1745
|
+
ossl_ssl_data_get_struct(self, ssl);
|
1318
1746
|
|
1319
1747
|
SafeGetSSLSession(arg1, sess);
|
1320
1748
|
|
@@ -1324,58 +1752,319 @@ ossl_ssl_set_session(VALUE self, VALUE arg1)
|
|
1324
1752
|
return arg1;
|
1325
1753
|
}
|
1326
1754
|
|
1755
|
+
/*
|
1756
|
+
* call-seq:
|
1757
|
+
* ssl.verify_result => Integer
|
1758
|
+
*
|
1759
|
+
* Returns the result of the peer certificates verification. See verify(1)
|
1760
|
+
* for error values and descriptions.
|
1761
|
+
*
|
1762
|
+
* If no peer certificate was presented X509_V_OK is returned.
|
1763
|
+
*/
|
1327
1764
|
static VALUE
|
1328
1765
|
ossl_ssl_get_verify_result(VALUE self)
|
1329
1766
|
{
|
1330
1767
|
SSL *ssl;
|
1331
1768
|
|
1332
|
-
|
1333
|
-
if (!ssl) {
|
1334
|
-
rb_warning("SSL session is not started yet.");
|
1335
|
-
return Qnil;
|
1336
|
-
}
|
1769
|
+
ossl_ssl_data_get_struct(self, ssl);
|
1337
1770
|
|
1338
1771
|
return INT2FIX(SSL_get_verify_result(ssl));
|
1339
1772
|
}
|
1340
1773
|
|
1774
|
+
/*
|
1775
|
+
* call-seq:
|
1776
|
+
* ssl.client_ca => [x509name, ...]
|
1777
|
+
*
|
1778
|
+
* Returns the list of client CAs. Please note that in contrast to
|
1779
|
+
* SSLContext#client_ca= no array of X509::Certificate is returned but
|
1780
|
+
* X509::Name instances of the CA's subject distinguished name.
|
1781
|
+
*
|
1782
|
+
* In server mode, returns the list set by SSLContext#client_ca=.
|
1783
|
+
* In client mode, returns the list of client CAs sent from the server.
|
1784
|
+
*/
|
1785
|
+
static VALUE
|
1786
|
+
ossl_ssl_get_client_ca_list(VALUE self)
|
1787
|
+
{
|
1788
|
+
SSL *ssl;
|
1789
|
+
STACK_OF(X509_NAME) *ca;
|
1790
|
+
|
1791
|
+
ossl_ssl_data_get_struct(self, ssl);
|
1792
|
+
|
1793
|
+
ca = SSL_get_client_CA_list(ssl);
|
1794
|
+
return ossl_x509name_sk2ary(ca);
|
1795
|
+
}
|
1796
|
+
|
1797
|
+
#ifdef HAVE_OPENSSL_NPN_NEGOTIATED
|
1798
|
+
/*
|
1799
|
+
* call-seq:
|
1800
|
+
* ssl.npn_protocol => String
|
1801
|
+
*
|
1802
|
+
* Returns the protocol string that was finally selected by the client
|
1803
|
+
* during the handshake.
|
1804
|
+
*/
|
1805
|
+
static VALUE
|
1806
|
+
ossl_ssl_npn_protocol(VALUE self)
|
1807
|
+
{
|
1808
|
+
SSL *ssl;
|
1809
|
+
const unsigned char *out;
|
1810
|
+
unsigned int outlen;
|
1811
|
+
|
1812
|
+
ossl_ssl_data_get_struct(self, ssl);
|
1813
|
+
|
1814
|
+
SSL_get0_next_proto_negotiated(ssl, &out, &outlen);
|
1815
|
+
if (!outlen)
|
1816
|
+
return Qnil;
|
1817
|
+
else
|
1818
|
+
return rb_str_new((const char *) out, outlen);
|
1819
|
+
}
|
1820
|
+
#endif
|
1821
|
+
|
1341
1822
|
void
|
1342
1823
|
Init_ossl_ssl()
|
1343
1824
|
{
|
1344
1825
|
int i;
|
1345
1826
|
VALUE ary;
|
1346
1827
|
|
1347
|
-
#if 0
|
1348
|
-
mOSSL = rb_define_module("OpenSSL");
|
1828
|
+
#if 0
|
1829
|
+
mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
|
1349
1830
|
#endif
|
1350
1831
|
|
1351
1832
|
ID_callback_state = rb_intern("@callback_state");
|
1352
1833
|
|
1353
|
-
ossl_ssl_ex_vcb_idx = SSL_get_ex_new_index(0,"ossl_ssl_ex_vcb_idx",0,0,0);
|
1354
|
-
ossl_ssl_ex_store_p = SSL_get_ex_new_index(0,"ossl_ssl_ex_store_p",0,0,0);
|
1355
|
-
ossl_ssl_ex_ptr_idx = SSL_get_ex_new_index(0,"ossl_ssl_ex_ptr_idx",0,0,0);
|
1834
|
+
ossl_ssl_ex_vcb_idx = SSL_get_ex_new_index(0,(void *)"ossl_ssl_ex_vcb_idx",0,0,0);
|
1835
|
+
ossl_ssl_ex_store_p = SSL_get_ex_new_index(0,(void *)"ossl_ssl_ex_store_p",0,0,0);
|
1836
|
+
ossl_ssl_ex_ptr_idx = SSL_get_ex_new_index(0,(void *)"ossl_ssl_ex_ptr_idx",0,0,0);
|
1356
1837
|
ossl_ssl_ex_client_cert_cb_idx =
|
1357
|
-
SSL_get_ex_new_index(0,"ossl_ssl_ex_client_cert_cb_idx",0,0,0);
|
1838
|
+
SSL_get_ex_new_index(0,(void *)"ossl_ssl_ex_client_cert_cb_idx",0,0,0);
|
1358
1839
|
ossl_ssl_ex_tmp_dh_callback_idx =
|
1359
|
-
SSL_get_ex_new_index(0,"ossl_ssl_ex_tmp_dh_callback_idx",0,0,0);
|
1840
|
+
SSL_get_ex_new_index(0,(void *)"ossl_ssl_ex_tmp_dh_callback_idx",0,0,0);
|
1360
1841
|
|
1842
|
+
/* Document-module: OpenSSL::SSL
|
1843
|
+
*
|
1844
|
+
* Use SSLContext to set up the parameters for a TLS (former SSL)
|
1845
|
+
* connection. Both client and server TLS connections are supported,
|
1846
|
+
* SSLSocket and SSLServer may be used in conjunction with an instance
|
1847
|
+
* of SSLContext to set up connections.
|
1848
|
+
*/
|
1361
1849
|
mSSL = rb_define_module_under(mOSSL, "SSL");
|
1850
|
+
/* Document-class: OpenSSL::SSL::SSLError
|
1851
|
+
*
|
1852
|
+
* Generic error class raised by SSLSocket and SSLContext.
|
1853
|
+
*/
|
1362
1854
|
eSSLError = rb_define_class_under(mSSL, "SSLError", eOSSLError);
|
1363
1855
|
|
1364
1856
|
Init_ossl_ssl_session();
|
1365
1857
|
|
1366
|
-
/* class SSLContext
|
1858
|
+
/* Document-class: OpenSSL::SSL::SSLContext
|
1367
1859
|
*
|
1368
|
-
*
|
1369
|
-
*
|
1860
|
+
* An SSLContext is used to set various options regarding certificates,
|
1861
|
+
* algorithms, verification, session caching, etc. The SSLContext is
|
1862
|
+
* used to create an SSLSocket.
|
1863
|
+
*
|
1864
|
+
* All attributes must be set before creating an SSLSocket as the
|
1865
|
+
* SSLContext will be frozen afterward.
|
1866
|
+
*
|
1867
|
+
* The following attributes are available but don't show up in rdoc:
|
1370
1868
|
* * ssl_version, cert, key, client_ca, ca_file, ca_path, timeout,
|
1371
1869
|
* * verify_mode, verify_depth client_cert_cb, tmp_dh_callback,
|
1372
1870
|
* * session_id_context, session_add_cb, session_new_cb, session_remove_cb
|
1373
1871
|
*/
|
1374
1872
|
cSSLContext = rb_define_class_under(mSSL, "SSLContext", rb_cObject);
|
1375
1873
|
rb_define_alloc_func(cSSLContext, ossl_sslctx_s_alloc);
|
1376
|
-
|
1377
|
-
|
1874
|
+
|
1875
|
+
/*
|
1876
|
+
* Context certificate
|
1877
|
+
*/
|
1878
|
+
rb_attr(cSSLContext, rb_intern("cert"), 1, 1, Qfalse);
|
1879
|
+
|
1880
|
+
/*
|
1881
|
+
* Context private key
|
1882
|
+
*/
|
1883
|
+
rb_attr(cSSLContext, rb_intern("key"), 1, 1, Qfalse);
|
1884
|
+
|
1885
|
+
/*
|
1886
|
+
* A certificate or Array of certificates that will be sent to the client.
|
1887
|
+
*/
|
1888
|
+
rb_attr(cSSLContext, rb_intern("client_ca"), 1, 1, Qfalse);
|
1889
|
+
|
1890
|
+
/*
|
1891
|
+
* The path to a file containing a PEM-format CA certificate
|
1892
|
+
*/
|
1893
|
+
rb_attr(cSSLContext, rb_intern("ca_file"), 1, 1, Qfalse);
|
1894
|
+
|
1895
|
+
/*
|
1896
|
+
* The path to a directory containing CA certificates in PEM format.
|
1897
|
+
*
|
1898
|
+
* Files are looked up by subject's X509 name's hash value.
|
1899
|
+
*/
|
1900
|
+
rb_attr(cSSLContext, rb_intern("ca_path"), 1, 1, Qfalse);
|
1901
|
+
|
1902
|
+
/*
|
1903
|
+
* Maximum session lifetime.
|
1904
|
+
*/
|
1905
|
+
rb_attr(cSSLContext, rb_intern("timeout"), 1, 1, Qfalse);
|
1906
|
+
|
1907
|
+
/*
|
1908
|
+
* Session verification mode.
|
1909
|
+
*
|
1910
|
+
* Valid modes are VERIFY_NONE, VERIFY_PEER, VERIFY_CLIENT_ONCE,
|
1911
|
+
* VERIFY_FAIL_IF_NO_PEER_CERT and defined on OpenSSL::SSL
|
1912
|
+
*/
|
1913
|
+
rb_attr(cSSLContext, rb_intern("verify_mode"), 1, 1, Qfalse);
|
1914
|
+
|
1915
|
+
/*
|
1916
|
+
* Number of CA certificates to walk when verifying a certificate chain.
|
1917
|
+
*/
|
1918
|
+
rb_attr(cSSLContext, rb_intern("verify_depth"), 1, 1, Qfalse);
|
1919
|
+
|
1920
|
+
/*
|
1921
|
+
* A callback for additional certificate verification. The callback is
|
1922
|
+
* invoked for each certificate in the chain.
|
1923
|
+
*
|
1924
|
+
* The callback is invoked with two values. +preverify_ok+ indicates
|
1925
|
+
* indicates if the verification was passed (true) or not (false).
|
1926
|
+
* +store_context+ is an OpenSSL::X509::StoreContext containing the
|
1927
|
+
* context used for certificate verification.
|
1928
|
+
*
|
1929
|
+
* If the callback returns false verification is stopped.
|
1930
|
+
*/
|
1931
|
+
rb_attr(cSSLContext, rb_intern("verify_callback"), 1, 1, Qfalse);
|
1932
|
+
|
1933
|
+
/*
|
1934
|
+
* Sets various OpenSSL options.
|
1935
|
+
*/
|
1936
|
+
rb_attr(cSSLContext, rb_intern("options"), 1, 1, Qfalse);
|
1937
|
+
|
1938
|
+
/*
|
1939
|
+
* An OpenSSL::X509::Store used for certificate verification
|
1940
|
+
*/
|
1941
|
+
rb_attr(cSSLContext, rb_intern("cert_store"), 1, 1, Qfalse);
|
1942
|
+
|
1943
|
+
/*
|
1944
|
+
* An Array of extra X509 certificates to be added to the certificate
|
1945
|
+
* chain.
|
1946
|
+
*/
|
1947
|
+
rb_attr(cSSLContext, rb_intern("extra_chain_cert"), 1, 1, Qfalse);
|
1948
|
+
|
1949
|
+
/*
|
1950
|
+
* A callback invoked when a client certificate is requested by a server
|
1951
|
+
* and no certificate has been set.
|
1952
|
+
*
|
1953
|
+
* The callback is invoked with a Session and must return an Array
|
1954
|
+
* containing an OpenSSL::X509::Certificate and an OpenSSL::PKey. If any
|
1955
|
+
* other value is returned the handshake is suspended.
|
1956
|
+
*/
|
1957
|
+
rb_attr(cSSLContext, rb_intern("client_cert_cb"), 1, 1, Qfalse);
|
1958
|
+
|
1959
|
+
/*
|
1960
|
+
* A callback invoked when DH parameters are required.
|
1961
|
+
*
|
1962
|
+
* The callback is invoked with the Session for the key exchange, an
|
1963
|
+
* flag indicating the use of an export cipher and the keylength
|
1964
|
+
* required.
|
1965
|
+
*
|
1966
|
+
* The callback must return an OpenSSL::PKey::DH instance of the correct
|
1967
|
+
* key length.
|
1968
|
+
*/
|
1969
|
+
rb_attr(cSSLContext, rb_intern("tmp_dh_callback"), 1, 1, Qfalse);
|
1970
|
+
|
1971
|
+
/*
|
1972
|
+
* Sets the context in which a session can be reused. This allows
|
1973
|
+
* sessions for multiple applications to be distinguished, for exapmle, by
|
1974
|
+
* name.
|
1975
|
+
*/
|
1976
|
+
rb_attr(cSSLContext, rb_intern("session_id_context"), 1, 1, Qfalse);
|
1977
|
+
|
1978
|
+
/*
|
1979
|
+
* A callback invoked on a server when a session is proposed by the client
|
1980
|
+
* but the session could not be found in the server's internal cache.
|
1981
|
+
*
|
1982
|
+
* The callback is invoked with the SSLSocket and session id. The
|
1983
|
+
* callback may return a Session from an external cache.
|
1984
|
+
*/
|
1985
|
+
rb_attr(cSSLContext, rb_intern("session_get_cb"), 1, 1, Qfalse);
|
1986
|
+
|
1987
|
+
/*
|
1988
|
+
* A callback invoked when a new session was negotiatied.
|
1989
|
+
*
|
1990
|
+
* The callback is invoked with an SSLSocket. If false is returned the
|
1991
|
+
* session will be removed from the internal cache.
|
1992
|
+
*/
|
1993
|
+
rb_attr(cSSLContext, rb_intern("session_new_cb"), 1, 1, Qfalse);
|
1994
|
+
|
1995
|
+
/*
|
1996
|
+
* A callback invoked when a session is removed from the internal cache.
|
1997
|
+
*
|
1998
|
+
* The callback is invoked with an SSLContext and a Session.
|
1999
|
+
*/
|
2000
|
+
rb_attr(cSSLContext, rb_intern("session_remove_cb"), 1, 1, Qfalse);
|
2001
|
+
|
2002
|
+
#ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME
|
2003
|
+
/*
|
2004
|
+
* A callback invoked at connect time to distinguish between multiple
|
2005
|
+
* server names.
|
2006
|
+
*
|
2007
|
+
* The callback is invoked with an SSLSocket and a server name. The
|
2008
|
+
* callback must return an SSLContext for the server name or nil.
|
2009
|
+
*/
|
2010
|
+
rb_attr(cSSLContext, rb_intern("servername_cb"), 1, 1, Qfalse);
|
2011
|
+
#endif
|
2012
|
+
/*
|
2013
|
+
* A callback invoked whenever a new handshake is initiated. May be used
|
2014
|
+
* to disable renegotiation entirely.
|
2015
|
+
*
|
2016
|
+
* The callback is invoked with the active SSLSocket. The callback's
|
2017
|
+
* return value is irrelevant, normal return indicates "approval" of the
|
2018
|
+
* renegotiation and will continue the process. To forbid renegotiation
|
2019
|
+
* and to cancel the process, an Error may be raised within the callback.
|
2020
|
+
*
|
2021
|
+
* === Disable client renegotiation
|
2022
|
+
*
|
2023
|
+
* When running a server, it is often desirable to disable client
|
2024
|
+
* renegotiation entirely. You may use a callback as follows to implement
|
2025
|
+
* this feature:
|
2026
|
+
*
|
2027
|
+
* num_handshakes = 0
|
2028
|
+
* ctx.renegotiation_cb = lambda do |ssl|
|
2029
|
+
* num_handshakes += 1
|
2030
|
+
* raise RuntimeError.new("Client renegotiation disabled") if num_handshakes > 1
|
2031
|
+
* end
|
2032
|
+
*/
|
2033
|
+
rb_attr(cSSLContext, rb_intern("renegotiation_cb"), 1, 1, Qfalse);
|
2034
|
+
#ifdef HAVE_OPENSSL_NPN_NEGOTIATED
|
2035
|
+
/*
|
2036
|
+
* An Enumerable of Strings. Each String represents a protocol to be
|
2037
|
+
* advertised as the list of supported protocols for Next Protocol
|
2038
|
+
* Negotiation. Supported in OpenSSL 1.0.1 and higher. Has no effect
|
2039
|
+
* on the client side. If not set explicitly, the NPN extension will
|
2040
|
+
* not be sent by the server in the handshake.
|
2041
|
+
*
|
2042
|
+
* === Example
|
2043
|
+
*
|
2044
|
+
* ctx.npn_protocols = ["http/1.1", "spdy/2"]
|
2045
|
+
*/
|
2046
|
+
rb_attr(cSSLContext, rb_intern("npn_protocols"), 1, 1, Qfalse);
|
2047
|
+
/*
|
2048
|
+
* A callback invoked on the client side when the client needs to select
|
2049
|
+
* a protocol from the list sent by the server. Supported in OpenSSL 1.0.1
|
2050
|
+
* and higher. The client MUST select a protocol of those advertised by
|
2051
|
+
* the server. If none is acceptable, raising an error in the callback
|
2052
|
+
* will cause the handshake to fail. Not setting this callback explicitly
|
2053
|
+
* means not supporting the NPN extension on the client - any protocols
|
2054
|
+
* advertised by the server will be ignored.
|
2055
|
+
*
|
2056
|
+
* === Example
|
2057
|
+
*
|
2058
|
+
* ctx.npn_select_cb = lambda do |protocols|
|
2059
|
+
* #inspect the protocols and select one
|
2060
|
+
* protocols.first
|
2061
|
+
* end
|
2062
|
+
*/
|
2063
|
+
rb_attr(cSSLContext, rb_intern("npn_select_cb"), 1, 1, Qfalse);
|
2064
|
+
#endif
|
2065
|
+
|
1378
2066
|
rb_define_alias(cSSLContext, "ssl_timeout", "timeout");
|
2067
|
+
rb_define_alias(cSSLContext, "ssl_timeout=", "timeout=");
|
1379
2068
|
rb_define_method(cSSLContext, "initialize", ossl_sslctx_initialize, -1);
|
1380
2069
|
rb_define_method(cSSLContext, "ssl_version=", ossl_sslctx_set_ssl_version, 1);
|
1381
2070
|
rb_define_method(cSSLContext, "ciphers", ossl_sslctx_get_ciphers, 0);
|
@@ -1383,15 +2072,53 @@ Init_ossl_ssl()
|
|
1383
2072
|
|
1384
2073
|
rb_define_method(cSSLContext, "setup", ossl_sslctx_setup, 0);
|
1385
2074
|
|
1386
|
-
|
2075
|
+
/*
|
2076
|
+
* No session caching for client or server
|
2077
|
+
*/
|
1387
2078
|
rb_define_const(cSSLContext, "SESSION_CACHE_OFF", LONG2FIX(SSL_SESS_CACHE_OFF));
|
2079
|
+
|
2080
|
+
/*
|
2081
|
+
* Client sessions are added to the session cache
|
2082
|
+
*/
|
1388
2083
|
rb_define_const(cSSLContext, "SESSION_CACHE_CLIENT", LONG2FIX(SSL_SESS_CACHE_CLIENT)); /* doesn't actually do anything in 0.9.8e */
|
2084
|
+
|
2085
|
+
/*
|
2086
|
+
* Server sessions are added to the session cache
|
2087
|
+
*/
|
1389
2088
|
rb_define_const(cSSLContext, "SESSION_CACHE_SERVER", LONG2FIX(SSL_SESS_CACHE_SERVER));
|
2089
|
+
|
2090
|
+
/*
|
2091
|
+
* Both client and server sessions are added to the session cache
|
2092
|
+
*/
|
1390
2093
|
rb_define_const(cSSLContext, "SESSION_CACHE_BOTH", LONG2FIX(SSL_SESS_CACHE_BOTH)); /* no different than CACHE_SERVER in 0.9.8e */
|
2094
|
+
|
2095
|
+
/*
|
2096
|
+
* Normally the session cache is checked for expired sessions every 255
|
2097
|
+
* connections. Since this may lead to a delay that cannot be controlled,
|
2098
|
+
* the automatic flushing may be disabled and #flush_sessions can be
|
2099
|
+
* called explicitly.
|
2100
|
+
*/
|
1391
2101
|
rb_define_const(cSSLContext, "SESSION_CACHE_NO_AUTO_CLEAR", LONG2FIX(SSL_SESS_CACHE_NO_AUTO_CLEAR));
|
2102
|
+
|
2103
|
+
/*
|
2104
|
+
* Always perform external lookups of sessions even if they are in the
|
2105
|
+
* internal cache.
|
2106
|
+
*
|
2107
|
+
* This flag has no effect on clients
|
2108
|
+
*/
|
1392
2109
|
rb_define_const(cSSLContext, "SESSION_CACHE_NO_INTERNAL_LOOKUP", LONG2FIX(SSL_SESS_CACHE_NO_INTERNAL_LOOKUP));
|
2110
|
+
|
2111
|
+
/*
|
2112
|
+
* Never automatically store sessions in the internal store.
|
2113
|
+
*/
|
1393
2114
|
rb_define_const(cSSLContext, "SESSION_CACHE_NO_INTERNAL_STORE", LONG2FIX(SSL_SESS_CACHE_NO_INTERNAL_STORE));
|
2115
|
+
|
2116
|
+
/*
|
2117
|
+
* Enables both SESSION_CACHE_NO_INTERNAL_LOOKUP and
|
2118
|
+
* SESSION_CACHE_NO_INTERNAL_STORE.
|
2119
|
+
*/
|
1394
2120
|
rb_define_const(cSSLContext, "SESSION_CACHE_NO_INTERNAL", LONG2FIX(SSL_SESS_CACHE_NO_INTERNAL));
|
2121
|
+
|
1395
2122
|
rb_define_method(cSSLContext, "session_add", ossl_sslctx_session_add, 1);
|
1396
2123
|
rb_define_method(cSSLContext, "session_remove", ossl_sslctx_session_remove, 1);
|
1397
2124
|
rb_define_method(cSSLContext, "session_cache_mode", ossl_sslctx_get_session_cache_mode, 0);
|
@@ -1406,10 +2133,11 @@ Init_ossl_ssl()
|
|
1406
2133
|
rb_ary_push(ary, ID2SYM(rb_intern(ossl_ssl_method_tab[i].name)));
|
1407
2134
|
}
|
1408
2135
|
rb_obj_freeze(ary);
|
1409
|
-
/*
|
2136
|
+
/* The list of available SSL/TLS methods */
|
1410
2137
|
rb_define_const(cSSLContext, "METHODS", ary);
|
1411
2138
|
|
1412
|
-
/*
|
2139
|
+
/*
|
2140
|
+
* Document-class: OpenSSL::SSL::SSLSocket
|
1413
2141
|
*
|
1414
2142
|
* The following attributes are available but don't show up in rdoc.
|
1415
2143
|
* * io, context, sync_close
|
@@ -1424,21 +2152,31 @@ Init_ossl_ssl()
|
|
1424
2152
|
rb_define_alias(cSSLSocket, "to_io", "io");
|
1425
2153
|
rb_define_method(cSSLSocket, "initialize", ossl_ssl_initialize, -1);
|
1426
2154
|
rb_define_method(cSSLSocket, "connect", ossl_ssl_connect, 0);
|
2155
|
+
rb_define_method(cSSLSocket, "connect_nonblock", ossl_ssl_connect_nonblock, 0);
|
1427
2156
|
rb_define_method(cSSLSocket, "accept", ossl_ssl_accept, 0);
|
2157
|
+
rb_define_method(cSSLSocket, "accept_nonblock", ossl_ssl_accept_nonblock, 0);
|
1428
2158
|
rb_define_method(cSSLSocket, "sysread", ossl_ssl_read, -1);
|
2159
|
+
rb_define_private_method(cSSLSocket, "sysread_nonblock", ossl_ssl_read_nonblock, -1);
|
1429
2160
|
rb_define_method(cSSLSocket, "syswrite", ossl_ssl_write, 1);
|
2161
|
+
rb_define_private_method(cSSLSocket, "syswrite_nonblock", ossl_ssl_write_nonblock, 1);
|
1430
2162
|
rb_define_method(cSSLSocket, "sysclose", ossl_ssl_close, 0);
|
1431
2163
|
rb_define_method(cSSLSocket, "cert", ossl_ssl_get_cert, 0);
|
1432
2164
|
rb_define_method(cSSLSocket, "peer_cert", ossl_ssl_get_peer_cert, 0);
|
1433
2165
|
rb_define_method(cSSLSocket, "peer_cert_chain", ossl_ssl_get_peer_cert_chain, 0);
|
2166
|
+
rb_define_method(cSSLSocket, "ssl_version", ossl_ssl_get_version, 0);
|
1434
2167
|
rb_define_method(cSSLSocket, "cipher", ossl_ssl_get_cipher, 0);
|
1435
2168
|
rb_define_method(cSSLSocket, "state", ossl_ssl_get_state, 0);
|
1436
2169
|
rb_define_method(cSSLSocket, "pending", ossl_ssl_pending, 0);
|
1437
2170
|
rb_define_method(cSSLSocket, "session_reused?", ossl_ssl_session_reused, 0);
|
2171
|
+
/* implementation of OpenSSL::SSL::SSLSocket#session is in lib/openssl/ssl.rb */
|
1438
2172
|
rb_define_method(cSSLSocket, "session=", ossl_ssl_set_session, 1);
|
1439
2173
|
rb_define_method(cSSLSocket, "verify_result", ossl_ssl_get_verify_result, 0);
|
2174
|
+
rb_define_method(cSSLSocket, "client_ca", ossl_ssl_get_client_ca_list, 0);
|
2175
|
+
#ifdef HAVE_OPENSSL_NPN_NEGOTIATED
|
2176
|
+
rb_define_method(cSSLSocket, "npn_protocol", ossl_ssl_npn_protocol, 0);
|
2177
|
+
#endif
|
1440
2178
|
|
1441
|
-
#define ossl_ssl_def_const(x) rb_define_const(mSSL, #x,
|
2179
|
+
#define ossl_ssl_def_const(x) rb_define_const(mSSL, #x, INT2NUM(SSL_##x))
|
1442
2180
|
|
1443
2181
|
ossl_ssl_def_const(VERIFY_NONE);
|
1444
2182
|
ossl_ssl_def_const(VERIFY_PEER);
|
@@ -1474,8 +2212,17 @@ Init_ossl_ssl()
|
|
1474
2212
|
ossl_ssl_def_const(OP_NO_SSLv2);
|
1475
2213
|
ossl_ssl_def_const(OP_NO_SSLv3);
|
1476
2214
|
ossl_ssl_def_const(OP_NO_TLSv1);
|
2215
|
+
#if defined(SSL_OP_NO_TLSv1_1)
|
2216
|
+
ossl_ssl_def_const(OP_NO_TLSv1_1);
|
2217
|
+
#endif
|
2218
|
+
#if defined(SSL_OP_NO_TLSv1_2)
|
2219
|
+
ossl_ssl_def_const(OP_NO_TLSv1_2);
|
2220
|
+
#endif
|
1477
2221
|
#if defined(SSL_OP_NO_TICKET)
|
1478
2222
|
ossl_ssl_def_const(OP_NO_TICKET);
|
2223
|
+
#endif
|
2224
|
+
#if defined(SSL_OP_NO_COMPRESSION)
|
2225
|
+
ossl_ssl_def_const(OP_NO_COMPRESSION);
|
1479
2226
|
#endif
|
1480
2227
|
ossl_ssl_def_const(OP_PKCS1_CHECK_1);
|
1481
2228
|
ossl_ssl_def_const(OP_PKCS1_CHECK_2);
|