rubysl-openssl 1.0.2 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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);
|