puma 2.2.0 → 8.0.2
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 +7 -0
- data/History.md +3334 -0
- data/LICENSE +23 -20
- data/README.md +387 -100
- data/bin/puma-wild +25 -0
- data/bin/pumactl +1 -1
- data/docs/5.0-Upgrade.md +98 -0
- data/docs/6.0-Upgrade.md +56 -0
- data/docs/7.0-Upgrade.md +52 -0
- data/docs/8.0-Upgrade.md +100 -0
- data/docs/architecture.md +74 -0
- data/docs/compile_options.md +55 -0
- data/docs/deployment.md +137 -0
- data/docs/fork_worker.md +41 -0
- data/docs/grpc.md +62 -0
- data/docs/images/favicon.svg +1 -0
- data/docs/images/puma-connection-flow-no-reactor.png +0 -0
- data/docs/images/puma-connection-flow.png +0 -0
- data/docs/images/puma-general-arch.png +0 -0
- data/docs/images/running-puma.svg +1 -0
- data/docs/images/standard-logo.svg +1 -0
- data/docs/java_options.md +54 -0
- data/docs/jungle/README.md +9 -0
- data/docs/jungle/rc.d/README.md +74 -0
- data/docs/jungle/rc.d/puma +61 -0
- data/docs/jungle/rc.d/puma.conf +10 -0
- data/docs/kubernetes.md +73 -0
- data/docs/nginx.md +5 -5
- data/docs/plugins.md +42 -0
- data/docs/rails_dev_mode.md +28 -0
- data/docs/restart.md +65 -0
- data/docs/signals.md +98 -0
- data/docs/stats.md +148 -0
- data/docs/systemd.md +253 -0
- data/docs/testing_benchmarks_local_files.md +150 -0
- data/docs/testing_test_rackup_ci_files.md +36 -0
- data/ext/puma_http11/PumaHttp11Service.java +2 -2
- data/ext/puma_http11/extconf.rb +59 -2
- data/ext/puma_http11/http11_parser.c +319 -487
- data/ext/puma_http11/http11_parser.h +15 -13
- data/ext/puma_http11/http11_parser.java.rl +64 -94
- data/ext/puma_http11/http11_parser.rl +27 -24
- data/ext/puma_http11/http11_parser_common.rl +8 -8
- data/ext/puma_http11/mini_ssl.c +696 -38
- data/ext/puma_http11/no_ssl/PumaHttp11Service.java +15 -0
- data/ext/puma_http11/org/jruby/puma/EnvKey.java +241 -0
- data/ext/puma_http11/org/jruby/puma/Http11.java +241 -145
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +174 -221
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +413 -193
- data/ext/puma_http11/puma_http11.c +183 -175
- data/lib/puma/app/status.rb +77 -29
- data/lib/puma/binder.rb +349 -119
- data/lib/puma/cli.rb +163 -801
- data/lib/puma/client.rb +627 -144
- data/lib/puma/client_env.rb +171 -0
- data/lib/puma/cluster/worker.rb +183 -0
- data/lib/puma/cluster/worker_handle.rb +127 -0
- data/lib/puma/cluster.rb +634 -0
- data/lib/puma/cluster_accept_loop_delay.rb +91 -0
- data/lib/puma/commonlogger.rb +115 -0
- data/lib/puma/configuration.rb +420 -198
- data/lib/puma/const.rb +266 -115
- data/lib/puma/control_cli.rb +219 -120
- data/lib/puma/detect.rb +56 -2
- data/lib/puma/dsl.rb +1562 -0
- data/lib/puma/error_logger.rb +115 -0
- data/lib/puma/events.rb +44 -60
- data/lib/puma/io_buffer.rb +48 -5
- data/lib/puma/jruby_restart.rb +2 -51
- data/lib/puma/json_serialization.rb +96 -0
- data/lib/puma/launcher/bundle_pruner.rb +102 -0
- data/lib/puma/launcher.rb +501 -0
- data/lib/puma/log_writer.rb +153 -0
- data/lib/puma/minissl/context_builder.rb +96 -0
- data/lib/puma/minissl.rb +355 -37
- data/lib/puma/null_io.rb +79 -12
- data/lib/puma/plugin/systemd.rb +90 -0
- data/lib/puma/plugin/tmp_restart.rb +36 -0
- data/lib/puma/plugin.rb +111 -0
- data/lib/puma/rack/builder.rb +297 -0
- data/lib/puma/rack/urlmap.rb +93 -0
- data/lib/puma/rack_default.rb +21 -4
- data/lib/puma/reactor.rb +102 -133
- data/lib/puma/response.rb +532 -0
- data/lib/puma/runner.rb +211 -0
- data/lib/puma/sd_notify.rb +146 -0
- data/lib/puma/server.rb +582 -445
- data/lib/puma/server_plugin_control.rb +32 -0
- data/lib/puma/single.rb +72 -0
- data/lib/puma/state_file.rb +69 -0
- data/lib/puma/thread_pool.rb +389 -57
- data/lib/puma/util.rb +125 -0
- data/lib/puma.rb +80 -6
- data/lib/rack/handler/puma.rb +125 -47
- data/tools/Dockerfile +26 -0
- data/tools/trickletest.rb +44 -0
- metadata +88 -148
- data/COPYING +0 -55
- data/Gemfile +0 -10
- data/History.txt +0 -302
- data/Manifest.txt +0 -60
- data/Rakefile +0 -165
- data/TODO +0 -5
- data/docs/config.md +0 -0
- data/ext/puma_http11/ext_help.h +0 -15
- data/ext/puma_http11/io_buffer.c +0 -154
- data/lib/puma/accept_nonblock.rb +0 -23
- data/lib/puma/capistrano.rb +0 -34
- data/lib/puma/compat.rb +0 -11
- data/lib/puma/daemon_ext.rb +0 -20
- data/lib/puma/delegation.rb +0 -11
- data/lib/puma/java_io_buffer.rb +0 -45
- data/lib/puma/rack_patch.rb +0 -25
- data/puma.gemspec +0 -45
- data/test/test_app_status.rb +0 -88
- data/test/test_cli.rb +0 -171
- data/test/test_config.rb +0 -16
- data/test/test_http10.rb +0 -27
- data/test/test_http11.rb +0 -126
- data/test/test_integration.rb +0 -154
- data/test/test_iobuffer.rb +0 -38
- data/test/test_minissl.rb +0 -25
- data/test/test_null_io.rb +0 -31
- data/test/test_persistent.rb +0 -238
- data/test/test_puma_server.rb +0 -224
- data/test/test_rack_handler.rb +0 -10
- data/test/test_rack_server.rb +0 -141
- data/test/test_thread_pool.rb +0 -146
- data/test/test_unix_socket.rb +0 -39
- data/test/test_ws.rb +0 -89
- data/tools/jungle/init.d/README.md +0 -54
- data/tools/jungle/init.d/puma +0 -332
- data/tools/jungle/init.d/run-puma +0 -3
- data/tools/jungle/upstart/README.md +0 -61
- data/tools/jungle/upstart/puma-manager.conf +0 -31
- data/tools/jungle/upstart/puma.conf +0 -52
data/ext/puma_http11/mini_ssl.c
CHANGED
|
@@ -1,8 +1,20 @@
|
|
|
1
|
+
#define RSTRING_NOT_MODIFIED 1
|
|
2
|
+
|
|
1
3
|
#include <ruby.h>
|
|
2
|
-
#include <
|
|
4
|
+
#include <ruby/version.h>
|
|
5
|
+
#include <ruby/io.h>
|
|
6
|
+
|
|
7
|
+
#ifdef HAVE_OPENSSL_BIO_H
|
|
8
|
+
|
|
3
9
|
#include <openssl/bio.h>
|
|
4
10
|
#include <openssl/ssl.h>
|
|
11
|
+
#include <openssl/dh.h>
|
|
5
12
|
#include <openssl/err.h>
|
|
13
|
+
#include <openssl/x509.h>
|
|
14
|
+
|
|
15
|
+
#ifndef SSL_OP_NO_COMPRESSION
|
|
16
|
+
#define SSL_OP_NO_COMPRESSION 0
|
|
17
|
+
#endif
|
|
6
18
|
|
|
7
19
|
typedef struct {
|
|
8
20
|
BIO* read;
|
|
@@ -11,17 +23,135 @@ typedef struct {
|
|
|
11
23
|
SSL_CTX* ctx;
|
|
12
24
|
} ms_conn;
|
|
13
25
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
26
|
+
typedef struct {
|
|
27
|
+
unsigned char* buf;
|
|
28
|
+
int bytes;
|
|
29
|
+
} ms_cert_buf;
|
|
30
|
+
|
|
31
|
+
VALUE eError;
|
|
32
|
+
|
|
33
|
+
NORETURN(void raise_file_error(const char* caller, const char *filename));
|
|
34
|
+
|
|
35
|
+
void raise_file_error(const char* caller, const char *filename) {
|
|
36
|
+
rb_raise(eError, "%s: error in file '%s': %s", caller, filename, ERR_error_string(ERR_get_error(), NULL));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
NORETURN(void raise_param_error(const char* caller, const char *param));
|
|
40
|
+
|
|
41
|
+
void raise_param_error(const char* caller, const char *param) {
|
|
42
|
+
rb_raise(eError, "%s: error with parameter '%s': %s", caller, param, ERR_error_string(ERR_get_error(), NULL));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
void engine_free(void *ptr) {
|
|
46
|
+
ms_conn *conn = ptr;
|
|
47
|
+
ms_cert_buf* cert_buf = (ms_cert_buf*)SSL_get_app_data(conn->ssl);
|
|
48
|
+
if(cert_buf) {
|
|
49
|
+
OPENSSL_free(cert_buf->buf);
|
|
50
|
+
free(cert_buf);
|
|
51
|
+
}
|
|
52
|
+
SSL_free(conn->ssl);
|
|
53
|
+
SSL_CTX_free(conn->ctx);
|
|
17
54
|
|
|
18
55
|
free(conn);
|
|
19
56
|
}
|
|
20
57
|
|
|
58
|
+
const rb_data_type_t engine_data_type = {
|
|
59
|
+
"MiniSSL/ENGINE",
|
|
60
|
+
{ 0, engine_free, 0 },
|
|
61
|
+
0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
#ifndef HAVE_SSL_CTX_SET_DH_AUTO
|
|
65
|
+
DH *get_dh2048(void) {
|
|
66
|
+
/* `openssl dhparam -C 2048`
|
|
67
|
+
* -----BEGIN DH PARAMETERS-----
|
|
68
|
+
* MIIBCAKCAQEAjmh1uQHdTfxOyxEbKAV30fUfzqMDF/ChPzjfyzl2jcrqQMhrk76o
|
|
69
|
+
* 2NPNXqxHwsddMZ1RzvU8/jl+uhRuPWjXCFZbhET4N1vrviZM3VJhV8PPHuiVOACO
|
|
70
|
+
* y32jFd+Szx4bo2cXSK83hJ6jRd+0asP1awWjz9/06dFkrILCXMIfQLo0D8rqmppn
|
|
71
|
+
* EfDDAwuudCpM9kcDmBRAm9JsKbQ6gzZWjkc5+QWSaQofojIHbjvj3xzguaCJn+oQ
|
|
72
|
+
* vHWM+hsAnaOgEwCyeZ3xqs+/5lwSbkE/tqJW98cEZGygBUVo9jxZRZx6KOfjpdrb
|
|
73
|
+
* yenO9LJr/qtyrZB31WJbqxI0m0AKTAO8UwIBAg==
|
|
74
|
+
* -----END DH PARAMETERS-----
|
|
75
|
+
*/
|
|
76
|
+
static unsigned char dh2048_p[] = {
|
|
77
|
+
0x8E, 0x68, 0x75, 0xB9, 0x01, 0xDD, 0x4D, 0xFC, 0x4E, 0xCB,
|
|
78
|
+
0x11, 0x1B, 0x28, 0x05, 0x77, 0xD1, 0xF5, 0x1F, 0xCE, 0xA3,
|
|
79
|
+
0x03, 0x17, 0xF0, 0xA1, 0x3F, 0x38, 0xDF, 0xCB, 0x39, 0x76,
|
|
80
|
+
0x8D, 0xCA, 0xEA, 0x40, 0xC8, 0x6B, 0x93, 0xBE, 0xA8, 0xD8,
|
|
81
|
+
0xD3, 0xCD, 0x5E, 0xAC, 0x47, 0xC2, 0xC7, 0x5D, 0x31, 0x9D,
|
|
82
|
+
0x51, 0xCE, 0xF5, 0x3C, 0xFE, 0x39, 0x7E, 0xBA, 0x14, 0x6E,
|
|
83
|
+
0x3D, 0x68, 0xD7, 0x08, 0x56, 0x5B, 0x84, 0x44, 0xF8, 0x37,
|
|
84
|
+
0x5B, 0xEB, 0xBE, 0x26, 0x4C, 0xDD, 0x52, 0x61, 0x57, 0xC3,
|
|
85
|
+
0xCF, 0x1E, 0xE8, 0x95, 0x38, 0x00, 0x8E, 0xCB, 0x7D, 0xA3,
|
|
86
|
+
0x15, 0xDF, 0x92, 0xCF, 0x1E, 0x1B, 0xA3, 0x67, 0x17, 0x48,
|
|
87
|
+
0xAF, 0x37, 0x84, 0x9E, 0xA3, 0x45, 0xDF, 0xB4, 0x6A, 0xC3,
|
|
88
|
+
0xF5, 0x6B, 0x05, 0xA3, 0xCF, 0xDF, 0xF4, 0xE9, 0xD1, 0x64,
|
|
89
|
+
0xAC, 0x82, 0xC2, 0x5C, 0xC2, 0x1F, 0x40, 0xBA, 0x34, 0x0F,
|
|
90
|
+
0xCA, 0xEA, 0x9A, 0x9A, 0x67, 0x11, 0xF0, 0xC3, 0x03, 0x0B,
|
|
91
|
+
0xAE, 0x74, 0x2A, 0x4C, 0xF6, 0x47, 0x03, 0x98, 0x14, 0x40,
|
|
92
|
+
0x9B, 0xD2, 0x6C, 0x29, 0xB4, 0x3A, 0x83, 0x36, 0x56, 0x8E,
|
|
93
|
+
0x47, 0x39, 0xF9, 0x05, 0x92, 0x69, 0x0A, 0x1F, 0xA2, 0x32,
|
|
94
|
+
0x07, 0x6E, 0x3B, 0xE3, 0xDF, 0x1C, 0xE0, 0xB9, 0xA0, 0x89,
|
|
95
|
+
0x9F, 0xEA, 0x10, 0xBC, 0x75, 0x8C, 0xFA, 0x1B, 0x00, 0x9D,
|
|
96
|
+
0xA3, 0xA0, 0x13, 0x00, 0xB2, 0x79, 0x9D, 0xF1, 0xAA, 0xCF,
|
|
97
|
+
0xBF, 0xE6, 0x5C, 0x12, 0x6E, 0x41, 0x3F, 0xB6, 0xA2, 0x56,
|
|
98
|
+
0xF7, 0xC7, 0x04, 0x64, 0x6C, 0xA0, 0x05, 0x45, 0x68, 0xF6,
|
|
99
|
+
0x3C, 0x59, 0x45, 0x9C, 0x7A, 0x28, 0xE7, 0xE3, 0xA5, 0xDA,
|
|
100
|
+
0xDB, 0xC9, 0xE9, 0xCE, 0xF4, 0xB2, 0x6B, 0xFE, 0xAB, 0x72,
|
|
101
|
+
0xAD, 0x90, 0x77, 0xD5, 0x62, 0x5B, 0xAB, 0x12, 0x34, 0x9B,
|
|
102
|
+
0x40, 0x0A, 0x4C, 0x03, 0xBC, 0x53
|
|
103
|
+
};
|
|
104
|
+
static unsigned char dh2048_g[] = { 0x02 };
|
|
105
|
+
|
|
106
|
+
DH *dh;
|
|
107
|
+
#if !(OPENSSL_VERSION_NUMBER < 0x10100005L)
|
|
108
|
+
BIGNUM *p, *g;
|
|
109
|
+
#endif
|
|
110
|
+
|
|
111
|
+
dh = DH_new();
|
|
112
|
+
|
|
113
|
+
#if OPENSSL_VERSION_NUMBER < 0x10100005L
|
|
114
|
+
dh->p = BN_bin2bn(dh2048_p, sizeof(dh2048_p), NULL);
|
|
115
|
+
dh->g = BN_bin2bn(dh2048_g, sizeof(dh2048_g), NULL);
|
|
116
|
+
|
|
117
|
+
if ((dh->p == NULL) || (dh->g == NULL)) {
|
|
118
|
+
DH_free(dh);
|
|
119
|
+
return NULL;
|
|
120
|
+
}
|
|
121
|
+
#else
|
|
122
|
+
p = BN_bin2bn(dh2048_p, sizeof(dh2048_p), NULL);
|
|
123
|
+
g = BN_bin2bn(dh2048_g, sizeof(dh2048_g), NULL);
|
|
124
|
+
|
|
125
|
+
if (p == NULL || g == NULL || !DH_set0_pqg(dh, p, NULL, g)) {
|
|
126
|
+
DH_free(dh);
|
|
127
|
+
BN_free(p);
|
|
128
|
+
BN_free(g);
|
|
129
|
+
return NULL;
|
|
130
|
+
}
|
|
131
|
+
#endif
|
|
132
|
+
|
|
133
|
+
return dh;
|
|
134
|
+
}
|
|
135
|
+
#endif
|
|
136
|
+
|
|
137
|
+
static void
|
|
138
|
+
sslctx_free(void *ptr) {
|
|
139
|
+
SSL_CTX *ctx = ptr;
|
|
140
|
+
SSL_CTX_free(ctx);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
static const rb_data_type_t sslctx_type = {
|
|
144
|
+
"MiniSSL/SSLContext",
|
|
145
|
+
{
|
|
146
|
+
0, sslctx_free,
|
|
147
|
+
},
|
|
148
|
+
0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
|
|
149
|
+
};
|
|
150
|
+
|
|
21
151
|
ms_conn* engine_alloc(VALUE klass, VALUE* obj) {
|
|
22
152
|
ms_conn* conn;
|
|
23
153
|
|
|
24
|
-
*obj =
|
|
154
|
+
*obj = TypedData_Make_Struct(klass, ms_conn, &engine_data_type, conn);
|
|
25
155
|
|
|
26
156
|
conn->read = BIO_new(BIO_s_mem());
|
|
27
157
|
BIO_set_nbio(conn->read, 1);
|
|
@@ -35,30 +165,349 @@ ms_conn* engine_alloc(VALUE klass, VALUE* obj) {
|
|
|
35
165
|
return conn;
|
|
36
166
|
}
|
|
37
167
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
SSL_CTX* ctx;
|
|
168
|
+
static int engine_verify_callback(int preverify_ok, X509_STORE_CTX* ctx) {
|
|
169
|
+
X509* err_cert;
|
|
41
170
|
SSL* ssl;
|
|
171
|
+
int bytes;
|
|
172
|
+
unsigned char* buf = NULL;
|
|
173
|
+
|
|
174
|
+
if(!preverify_ok) {
|
|
175
|
+
err_cert = X509_STORE_CTX_get_current_cert(ctx);
|
|
176
|
+
if(err_cert) {
|
|
177
|
+
/*
|
|
178
|
+
* Save the failed certificate for inspection/logging.
|
|
179
|
+
*/
|
|
180
|
+
bytes = i2d_X509(err_cert, &buf);
|
|
181
|
+
if(bytes > 0) {
|
|
182
|
+
ms_cert_buf* cert_buf = (ms_cert_buf*)malloc(sizeof(ms_cert_buf));
|
|
183
|
+
cert_buf->buf = buf;
|
|
184
|
+
cert_buf->bytes = bytes;
|
|
185
|
+
ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
|
|
186
|
+
SSL_set_app_data(ssl, cert_buf);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
42
190
|
|
|
43
|
-
|
|
191
|
+
return preverify_ok;
|
|
192
|
+
}
|
|
44
193
|
|
|
45
|
-
|
|
46
|
-
|
|
194
|
+
static int password_callback(char *buf, int size, int rwflag, void *userdata) {
|
|
195
|
+
const char *password = (const char *) userdata;
|
|
196
|
+
size_t len = strlen(password);
|
|
47
197
|
|
|
48
|
-
|
|
49
|
-
|
|
198
|
+
if (len > (size_t) size) {
|
|
199
|
+
return 0;
|
|
200
|
+
}
|
|
50
201
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
202
|
+
memcpy(buf, password, len);
|
|
203
|
+
return (int) len;
|
|
204
|
+
}
|
|
54
205
|
|
|
55
|
-
|
|
56
|
-
|
|
206
|
+
static VALUE
|
|
207
|
+
sslctx_alloc(VALUE klass) {
|
|
208
|
+
SSL_CTX *ctx;
|
|
209
|
+
long mode = 0 |
|
|
210
|
+
SSL_MODE_ENABLE_PARTIAL_WRITE |
|
|
211
|
+
SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
|
|
212
|
+
SSL_MODE_RELEASE_BUFFERS;
|
|
213
|
+
|
|
214
|
+
#ifdef HAVE_TLS_SERVER_METHOD
|
|
215
|
+
ctx = SSL_CTX_new(TLS_method());
|
|
216
|
+
// printf("\nctx using TLS_method security_level %d\n", SSL_CTX_get_security_level(ctx));
|
|
217
|
+
#else
|
|
218
|
+
ctx = SSL_CTX_new(SSLv23_method());
|
|
219
|
+
#endif
|
|
220
|
+
if (!ctx) {
|
|
221
|
+
rb_raise(eError, "SSL_CTX_new");
|
|
222
|
+
}
|
|
223
|
+
SSL_CTX_set_mode(ctx, mode);
|
|
57
224
|
|
|
58
|
-
|
|
225
|
+
return TypedData_Wrap_Struct(klass, &sslctx_type, ctx);
|
|
226
|
+
}
|
|
59
227
|
|
|
60
|
-
|
|
228
|
+
VALUE
|
|
229
|
+
sslctx_initialize(VALUE self, VALUE mini_ssl_ctx) {
|
|
230
|
+
SSL_CTX* ctx;
|
|
231
|
+
int ssl_options;
|
|
232
|
+
VALUE key, cert, ca, verify_mode, ssl_cipher_filter, ssl_ciphersuites, no_tlsv1, no_tlsv1_1,
|
|
233
|
+
verification_flags, session_id_bytes, cert_pem, key_pem, key_password_command, key_password;
|
|
234
|
+
BIO *bio;
|
|
235
|
+
X509 *x509 = NULL;
|
|
236
|
+
EVP_PKEY *pkey;
|
|
237
|
+
pem_password_cb *password_cb = NULL;
|
|
238
|
+
const char *password = NULL;
|
|
239
|
+
#ifdef HAVE_SSL_CTX_SET_MIN_PROTO_VERSION
|
|
240
|
+
int min;
|
|
241
|
+
#endif
|
|
242
|
+
#ifndef HAVE_SSL_CTX_SET_DH_AUTO
|
|
243
|
+
DH *dh;
|
|
244
|
+
#endif
|
|
245
|
+
#if OPENSSL_VERSION_NUMBER < 0x10002000L
|
|
246
|
+
EC_KEY *ecdh;
|
|
247
|
+
#endif
|
|
248
|
+
#ifdef HAVE_SSL_CTX_SET_SESSION_CACHE_MODE
|
|
249
|
+
VALUE reuse, reuse_cache_size, reuse_timeout;
|
|
250
|
+
|
|
251
|
+
reuse = rb_funcall(mini_ssl_ctx, rb_intern_const("reuse"), 0);
|
|
252
|
+
reuse_cache_size = rb_funcall(mini_ssl_ctx, rb_intern_const("reuse_cache_size"), 0);
|
|
253
|
+
reuse_timeout = rb_funcall(mini_ssl_ctx, rb_intern_const("reuse_timeout"), 0);
|
|
254
|
+
#endif
|
|
255
|
+
|
|
256
|
+
key = rb_funcall(mini_ssl_ctx, rb_intern_const("key"), 0);
|
|
257
|
+
|
|
258
|
+
key_password_command = rb_funcall(mini_ssl_ctx, rb_intern_const("key_password_command"), 0);
|
|
259
|
+
|
|
260
|
+
cert = rb_funcall(mini_ssl_ctx, rb_intern_const("cert"), 0);
|
|
261
|
+
|
|
262
|
+
ca = rb_funcall(mini_ssl_ctx, rb_intern_const("ca"), 0);
|
|
263
|
+
|
|
264
|
+
cert_pem = rb_funcall(mini_ssl_ctx, rb_intern_const("cert_pem"), 0);
|
|
265
|
+
|
|
266
|
+
key_pem = rb_funcall(mini_ssl_ctx, rb_intern_const("key_pem"), 0);
|
|
267
|
+
|
|
268
|
+
verify_mode = rb_funcall(mini_ssl_ctx, rb_intern_const("verify_mode"), 0);
|
|
269
|
+
|
|
270
|
+
ssl_cipher_filter = rb_funcall(mini_ssl_ctx, rb_intern_const("ssl_cipher_filter"), 0);
|
|
271
|
+
|
|
272
|
+
ssl_ciphersuites = rb_funcall(mini_ssl_ctx, rb_intern_const("ssl_ciphersuites"), 0);
|
|
273
|
+
|
|
274
|
+
no_tlsv1 = rb_funcall(mini_ssl_ctx, rb_intern_const("no_tlsv1"), 0);
|
|
275
|
+
|
|
276
|
+
no_tlsv1_1 = rb_funcall(mini_ssl_ctx, rb_intern_const("no_tlsv1_1"), 0);
|
|
277
|
+
|
|
278
|
+
TypedData_Get_Struct(self, SSL_CTX, &sslctx_type, ctx);
|
|
279
|
+
|
|
280
|
+
if (!NIL_P(cert)) {
|
|
281
|
+
StringValue(cert);
|
|
282
|
+
|
|
283
|
+
if (SSL_CTX_use_certificate_chain_file(ctx, RSTRING_PTR(cert)) != 1) {
|
|
284
|
+
raise_file_error("SSL_CTX_use_certificate_chain_file", RSTRING_PTR(cert));
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
if (!NIL_P(key_password_command)) {
|
|
289
|
+
key_password = rb_funcall(mini_ssl_ctx, rb_intern_const("key_password"), 0);
|
|
290
|
+
|
|
291
|
+
if (!NIL_P(key_password)) {
|
|
292
|
+
StringValue(key_password);
|
|
293
|
+
password_cb = password_callback;
|
|
294
|
+
password = RSTRING_PTR(key_password);
|
|
295
|
+
SSL_CTX_set_default_passwd_cb(ctx, password_cb);
|
|
296
|
+
SSL_CTX_set_default_passwd_cb_userdata(ctx, (void *) password);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
if (!NIL_P(key)) {
|
|
301
|
+
StringValue(key);
|
|
302
|
+
|
|
303
|
+
if (SSL_CTX_use_PrivateKey_file(ctx, RSTRING_PTR(key), SSL_FILETYPE_PEM) != 1) {
|
|
304
|
+
raise_file_error("SSL_CTX_use_PrivateKey_file", RSTRING_PTR(key));
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
if (!NIL_P(cert_pem)) {
|
|
309
|
+
X509 *ca = NULL;
|
|
310
|
+
unsigned long err;
|
|
311
|
+
|
|
312
|
+
bio = BIO_new(BIO_s_mem());
|
|
313
|
+
BIO_puts(bio, RSTRING_PTR(cert_pem));
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Much of this pulled as a simplified version of the `use_certificate_chain_file` method
|
|
317
|
+
* from openssl's `ssl_rsa.c` file.
|
|
318
|
+
*/
|
|
319
|
+
|
|
320
|
+
/* first read the cert as the first item in the pem file */
|
|
321
|
+
x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
|
|
322
|
+
if (NULL == x509) {
|
|
323
|
+
BIO_free_all(bio);
|
|
324
|
+
raise_param_error("PEM_read_bio_X509", "cert_pem");
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/* Add the cert to the context */
|
|
328
|
+
/* 1 is success - otherwise check the error codes */
|
|
329
|
+
if (1 != SSL_CTX_use_certificate(ctx, x509)) {
|
|
330
|
+
BIO_free_all(bio);
|
|
331
|
+
raise_param_error("SSL_CTX_use_certificate", "cert_pem");
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
X509_free(x509); /* no longer need our reference */
|
|
335
|
+
|
|
336
|
+
/* Now lets load up the rest of the certificate chain */
|
|
337
|
+
/* 1 is success 0 is error */
|
|
338
|
+
if (0 == SSL_CTX_clear_chain_certs(ctx)) {
|
|
339
|
+
BIO_free_all(bio);
|
|
340
|
+
raise_param_error("SSL_CTX_clear_chain_certs","cert_pem");
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
while (1) {
|
|
344
|
+
ca = PEM_read_bio_X509(bio, NULL, NULL, NULL);
|
|
345
|
+
|
|
346
|
+
if (NULL == ca) {
|
|
347
|
+
break;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
if (0 == SSL_CTX_add0_chain_cert(ctx, ca)) {
|
|
351
|
+
BIO_free_all(bio);
|
|
352
|
+
raise_param_error("SSL_CTX_add0_chain_cert","cert_pem");
|
|
353
|
+
}
|
|
354
|
+
/* don't free ca - its now owned by the context */
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/* ca is NULL - so its either the end of the file or an error */
|
|
358
|
+
err = ERR_peek_last_error();
|
|
359
|
+
|
|
360
|
+
/* If its the end of the file - then we are done, in any case free the bio */
|
|
361
|
+
BIO_free_all(bio);
|
|
362
|
+
|
|
363
|
+
if ((ERR_GET_LIB(err) == ERR_LIB_PEM) && (ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
|
|
364
|
+
ERR_clear_error();
|
|
365
|
+
} else {
|
|
366
|
+
raise_param_error("PEM_read_bio_X509","cert_pem");
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
if (!NIL_P(key_pem)) {
|
|
371
|
+
bio = BIO_new(BIO_s_mem());
|
|
372
|
+
BIO_puts(bio, RSTRING_PTR(key_pem));
|
|
373
|
+
pkey = PEM_read_bio_PrivateKey(bio, NULL, password_cb, (void *) password);
|
|
374
|
+
|
|
375
|
+
if (SSL_CTX_use_PrivateKey(ctx, pkey) != 1) {
|
|
376
|
+
BIO_free(bio);
|
|
377
|
+
raise_file_error("SSL_CTX_use_PrivateKey", RSTRING_PTR(key_pem));
|
|
378
|
+
}
|
|
379
|
+
EVP_PKEY_free(pkey);
|
|
380
|
+
BIO_free(bio);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
verification_flags = rb_funcall(mini_ssl_ctx, rb_intern_const("verification_flags"), 0);
|
|
384
|
+
|
|
385
|
+
if (!NIL_P(verification_flags)) {
|
|
386
|
+
X509_VERIFY_PARAM *param = SSL_CTX_get0_param(ctx);
|
|
387
|
+
X509_VERIFY_PARAM_set_flags(param, NUM2INT(verification_flags));
|
|
388
|
+
SSL_CTX_set1_param(ctx, param);
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
if (!NIL_P(ca)) {
|
|
392
|
+
StringValue(ca);
|
|
393
|
+
if (SSL_CTX_load_verify_locations(ctx, RSTRING_PTR(ca), NULL) != 1) {
|
|
394
|
+
raise_file_error("SSL_CTX_load_verify_locations", RSTRING_PTR(ca));
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
ssl_options = SSL_OP_CIPHER_SERVER_PREFERENCE | SSL_OP_SINGLE_ECDH_USE | SSL_OP_NO_COMPRESSION;
|
|
399
|
+
|
|
400
|
+
#ifdef HAVE_SSL_CTX_SET_MIN_PROTO_VERSION
|
|
401
|
+
if (RTEST(no_tlsv1_1)) {
|
|
402
|
+
min = TLS1_2_VERSION;
|
|
403
|
+
}
|
|
404
|
+
else if (RTEST(no_tlsv1)) {
|
|
405
|
+
min = TLS1_1_VERSION;
|
|
406
|
+
}
|
|
407
|
+
else {
|
|
408
|
+
min = TLS1_VERSION;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
SSL_CTX_set_min_proto_version(ctx, min);
|
|
412
|
+
|
|
413
|
+
#else
|
|
414
|
+
/* As of 1.0.2f, SSL_OP_SINGLE_DH_USE key use is always on */
|
|
415
|
+
ssl_options |= SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_SINGLE_DH_USE;
|
|
416
|
+
|
|
417
|
+
if (RTEST(no_tlsv1)) {
|
|
418
|
+
ssl_options |= SSL_OP_NO_TLSv1;
|
|
419
|
+
}
|
|
420
|
+
if(RTEST(no_tlsv1_1)) {
|
|
421
|
+
ssl_options |= SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1;
|
|
422
|
+
}
|
|
423
|
+
#endif
|
|
424
|
+
|
|
425
|
+
#ifdef HAVE_SSL_CTX_SET_SESSION_CACHE_MODE
|
|
426
|
+
if (!NIL_P(reuse)) {
|
|
427
|
+
SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER);
|
|
428
|
+
if (!NIL_P(reuse_cache_size)) {
|
|
429
|
+
SSL_CTX_sess_set_cache_size(ctx, NUM2INT(reuse_cache_size));
|
|
430
|
+
}
|
|
431
|
+
if (!NIL_P(reuse_timeout)) {
|
|
432
|
+
SSL_CTX_set_timeout(ctx, NUM2INT(reuse_timeout));
|
|
433
|
+
}
|
|
434
|
+
} else {
|
|
435
|
+
SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
|
|
436
|
+
}
|
|
437
|
+
#endif
|
|
438
|
+
|
|
439
|
+
SSL_CTX_set_options(ctx, ssl_options);
|
|
440
|
+
|
|
441
|
+
if (!NIL_P(ssl_cipher_filter)) {
|
|
442
|
+
StringValue(ssl_cipher_filter);
|
|
443
|
+
SSL_CTX_set_cipher_list(ctx, RSTRING_PTR(ssl_cipher_filter));
|
|
444
|
+
}
|
|
445
|
+
else {
|
|
446
|
+
SSL_CTX_set_cipher_list(ctx, "HIGH:!aNULL@STRENGTH");
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
#if HAVE_SSL_CTX_SET_CIPHERSUITES
|
|
450
|
+
// Only override OpenSSL default ciphersuites if config option is supplied.
|
|
451
|
+
if (!NIL_P(ssl_ciphersuites)) {
|
|
452
|
+
StringValue(ssl_ciphersuites);
|
|
453
|
+
SSL_CTX_set_ciphersuites(ctx, RSTRING_PTR(ssl_ciphersuites));
|
|
454
|
+
}
|
|
455
|
+
#endif
|
|
456
|
+
|
|
457
|
+
#if OPENSSL_VERSION_NUMBER < 0x10002000L
|
|
458
|
+
// Remove this case if OpenSSL 1.0.1 (now EOL) support is no longer needed.
|
|
459
|
+
ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
|
|
460
|
+
if (ecdh) {
|
|
461
|
+
SSL_CTX_set_tmp_ecdh(ctx, ecdh);
|
|
462
|
+
EC_KEY_free(ecdh);
|
|
463
|
+
}
|
|
464
|
+
#elif OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
|
|
465
|
+
SSL_CTX_set_ecdh_auto(ctx, 1);
|
|
466
|
+
#endif
|
|
467
|
+
|
|
468
|
+
if (NIL_P(verify_mode)) {
|
|
469
|
+
/* SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); */
|
|
470
|
+
} else {
|
|
471
|
+
SSL_CTX_set_verify(ctx, NUM2INT(verify_mode), engine_verify_callback);
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
session_id_bytes = rb_funcall(
|
|
475
|
+
rb_cRandom,
|
|
476
|
+
rb_intern_const("bytes"),
|
|
477
|
+
1, ULL2NUM(SSL_MAX_SSL_SESSION_ID_LENGTH));
|
|
478
|
+
|
|
479
|
+
SSL_CTX_set_session_id_context(ctx,
|
|
480
|
+
(unsigned char *) RSTRING_PTR(session_id_bytes),
|
|
481
|
+
SSL_MAX_SSL_SESSION_ID_LENGTH);
|
|
61
482
|
|
|
483
|
+
// printf("\ninitialize end security_level %d\n", SSL_CTX_get_security_level(ctx));
|
|
484
|
+
|
|
485
|
+
#ifdef HAVE_SSL_CTX_SET_DH_AUTO
|
|
486
|
+
// https://www.openssl.org/docs/man3.0/man3/SSL_CTX_set_dh_auto.html
|
|
487
|
+
SSL_CTX_set_dh_auto(ctx, 1);
|
|
488
|
+
#else
|
|
489
|
+
dh = get_dh2048();
|
|
490
|
+
SSL_CTX_set_tmp_dh(ctx, dh);
|
|
491
|
+
#endif
|
|
492
|
+
|
|
493
|
+
rb_obj_freeze(self);
|
|
494
|
+
return self;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
VALUE engine_init_server(VALUE self, VALUE sslctx) {
|
|
498
|
+
ms_conn* conn;
|
|
499
|
+
VALUE obj;
|
|
500
|
+
SSL_CTX* ctx;
|
|
501
|
+
SSL* ssl;
|
|
502
|
+
|
|
503
|
+
conn = engine_alloc(self, &obj);
|
|
504
|
+
|
|
505
|
+
TypedData_Get_Struct(sslctx, SSL_CTX, &sslctx_type, ctx);
|
|
506
|
+
|
|
507
|
+
ssl = SSL_new(ctx);
|
|
508
|
+
conn->ssl = ssl;
|
|
509
|
+
SSL_set_app_data(ssl, NULL);
|
|
510
|
+
SSL_set_bio(ssl, conn->read, conn->write);
|
|
62
511
|
SSL_set_accept_state(ssl);
|
|
63
512
|
return obj;
|
|
64
513
|
}
|
|
@@ -66,9 +515,13 @@ VALUE engine_init_server(VALUE self, VALUE key, VALUE cert) {
|
|
|
66
515
|
VALUE engine_init_client(VALUE klass) {
|
|
67
516
|
VALUE obj;
|
|
68
517
|
ms_conn* conn = engine_alloc(klass, &obj);
|
|
69
|
-
|
|
518
|
+
#ifdef HAVE_DTLS_METHOD
|
|
519
|
+
conn->ctx = SSL_CTX_new(DTLS_method());
|
|
520
|
+
#else
|
|
70
521
|
conn->ctx = SSL_CTX_new(DTLSv1_method());
|
|
522
|
+
#endif
|
|
71
523
|
conn->ssl = SSL_new(conn->ctx);
|
|
524
|
+
SSL_set_app_data(conn->ssl, NULL);
|
|
72
525
|
SSL_set_verify(conn->ssl, SSL_VERIFY_NONE, NULL);
|
|
73
526
|
|
|
74
527
|
SSL_set_bio(conn->ssl, conn->read, conn->write);
|
|
@@ -81,7 +534,7 @@ VALUE engine_inject(VALUE self, VALUE str) {
|
|
|
81
534
|
ms_conn* conn;
|
|
82
535
|
long used;
|
|
83
536
|
|
|
84
|
-
|
|
537
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
|
85
538
|
|
|
86
539
|
StringValue(str);
|
|
87
540
|
|
|
@@ -94,22 +547,48 @@ VALUE engine_inject(VALUE self, VALUE str) {
|
|
|
94
547
|
return INT2FIX(used);
|
|
95
548
|
}
|
|
96
549
|
|
|
97
|
-
|
|
550
|
+
NORETURN(void raise_error(SSL* ssl, int result));
|
|
98
551
|
|
|
99
552
|
void raise_error(SSL* ssl, int result) {
|
|
100
|
-
|
|
101
|
-
char
|
|
553
|
+
char buf[512];
|
|
554
|
+
char msg[768];
|
|
555
|
+
const char* err_str;
|
|
556
|
+
int err = errno;
|
|
557
|
+
int mask = 4095;
|
|
558
|
+
int ssl_err = SSL_get_error(ssl, result);
|
|
559
|
+
int verify_err = (int) SSL_get_verify_result(ssl);
|
|
560
|
+
|
|
561
|
+
if(SSL_ERROR_SYSCALL == ssl_err) {
|
|
562
|
+
snprintf(msg, sizeof(msg), "System error: %s - %d", strerror(err), err);
|
|
563
|
+
|
|
564
|
+
} else if(SSL_ERROR_SSL == ssl_err) {
|
|
565
|
+
if(X509_V_OK != verify_err) {
|
|
566
|
+
err_str = X509_verify_cert_error_string(verify_err);
|
|
567
|
+
snprintf(msg, sizeof(msg),
|
|
568
|
+
"OpenSSL certificate verification error: %s - %d",
|
|
569
|
+
err_str, verify_err);
|
|
570
|
+
|
|
571
|
+
} else {
|
|
572
|
+
err = (int) ERR_get_error();
|
|
573
|
+
ERR_error_string_n(err, buf, sizeof(buf));
|
|
574
|
+
snprintf(msg, sizeof(msg), "OpenSSL error: %s - %d", buf, err & mask);
|
|
575
|
+
}
|
|
576
|
+
} else {
|
|
577
|
+
snprintf(msg, sizeof(msg), "Unknown OpenSSL error: %d", ssl_err);
|
|
578
|
+
}
|
|
102
579
|
|
|
103
580
|
ERR_clear_error();
|
|
104
|
-
rb_raise(eError, "
|
|
581
|
+
rb_raise(eError, "%s", msg);
|
|
105
582
|
}
|
|
106
583
|
|
|
107
584
|
VALUE engine_read(VALUE self) {
|
|
108
585
|
ms_conn* conn;
|
|
109
586
|
char buf[512];
|
|
110
|
-
int bytes,
|
|
587
|
+
int bytes, error;
|
|
588
|
+
|
|
589
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
|
111
590
|
|
|
112
|
-
|
|
591
|
+
ERR_clear_error();
|
|
113
592
|
|
|
114
593
|
bytes = SSL_read(conn->ssl, (void*)buf, sizeof(buf));
|
|
115
594
|
|
|
@@ -119,24 +598,27 @@ VALUE engine_read(VALUE self) {
|
|
|
119
598
|
|
|
120
599
|
if(SSL_want_read(conn->ssl)) return Qnil;
|
|
121
600
|
|
|
122
|
-
|
|
601
|
+
error = SSL_get_error(conn->ssl, bytes);
|
|
602
|
+
|
|
603
|
+
if(error == SSL_ERROR_ZERO_RETURN) {
|
|
123
604
|
rb_eof_error();
|
|
605
|
+
} else {
|
|
606
|
+
raise_error(conn->ssl, bytes);
|
|
124
607
|
}
|
|
125
608
|
|
|
126
|
-
raise_error(conn->ssl, bytes);
|
|
127
|
-
|
|
128
609
|
return Qnil;
|
|
129
610
|
}
|
|
130
611
|
|
|
131
612
|
VALUE engine_write(VALUE self, VALUE str) {
|
|
132
613
|
ms_conn* conn;
|
|
133
|
-
char buf[512];
|
|
134
614
|
int bytes;
|
|
135
615
|
|
|
136
|
-
|
|
616
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
|
137
617
|
|
|
138
618
|
StringValue(str);
|
|
139
619
|
|
|
620
|
+
ERR_clear_error();
|
|
621
|
+
|
|
140
622
|
bytes = SSL_write(conn->ssl, (void*)RSTRING_PTR(str), (int)RSTRING_LEN(str));
|
|
141
623
|
if(bytes > 0) {
|
|
142
624
|
return INT2FIX(bytes);
|
|
@@ -153,9 +635,11 @@ VALUE engine_extract(VALUE self) {
|
|
|
153
635
|
ms_conn* conn;
|
|
154
636
|
int bytes;
|
|
155
637
|
size_t pending;
|
|
156
|
-
|
|
638
|
+
// https://www.openssl.org/docs/manmaster/man3/BIO_f_buffer.html
|
|
639
|
+
// crypto/bio/bf_buff.c DEFAULT_BUFFER_SIZE
|
|
640
|
+
char buf[4096];
|
|
157
641
|
|
|
158
|
-
|
|
642
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
|
159
643
|
|
|
160
644
|
pending = BIO_pending(conn->write);
|
|
161
645
|
if(pending > 0) {
|
|
@@ -170,20 +654,164 @@ VALUE engine_extract(VALUE self) {
|
|
|
170
654
|
return Qnil;
|
|
171
655
|
}
|
|
172
656
|
|
|
657
|
+
VALUE engine_shutdown(VALUE self) {
|
|
658
|
+
ms_conn* conn;
|
|
659
|
+
int ok;
|
|
660
|
+
|
|
661
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
|
662
|
+
|
|
663
|
+
if (SSL_in_init(conn->ssl)) {
|
|
664
|
+
// Avoid "shutdown while in init" error
|
|
665
|
+
// See https://github.com/openssl/openssl/blob/openssl-3.5.2/ssl/ssl_lib.c#L2827-L2828
|
|
666
|
+
return Qtrue;
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
ERR_clear_error();
|
|
670
|
+
|
|
671
|
+
ok = SSL_shutdown(conn->ssl);
|
|
672
|
+
// See https://github.com/openssl/openssl/blob/openssl-3.5.2/ssl/ssl_lib.c#L2792-L2797
|
|
673
|
+
// for description of SSL_shutdown return values.
|
|
674
|
+
switch (ok) {
|
|
675
|
+
case 0:
|
|
676
|
+
// "close notify" alert is sent by us.
|
|
677
|
+
return Qfalse;
|
|
678
|
+
case 1:
|
|
679
|
+
// "close notify" alert was received from peer.
|
|
680
|
+
return Qtrue;
|
|
681
|
+
default:
|
|
682
|
+
raise_error(conn->ssl, ok);
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
return Qnil;
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
VALUE engine_init(VALUE self) {
|
|
689
|
+
ms_conn* conn;
|
|
690
|
+
|
|
691
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
|
692
|
+
|
|
693
|
+
return SSL_in_init(conn->ssl) ? Qtrue : Qfalse;
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
VALUE engine_peercert(VALUE self) {
|
|
697
|
+
ms_conn* conn;
|
|
698
|
+
X509* cert;
|
|
699
|
+
int bytes;
|
|
700
|
+
unsigned char* buf = NULL;
|
|
701
|
+
ms_cert_buf* cert_buf = NULL;
|
|
702
|
+
VALUE rb_cert_buf;
|
|
703
|
+
|
|
704
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
|
705
|
+
|
|
706
|
+
#ifdef HAVE_SSL_GET1_PEER_CERTIFICATE
|
|
707
|
+
cert = SSL_get1_peer_certificate(conn->ssl);
|
|
708
|
+
#else
|
|
709
|
+
cert = SSL_get_peer_certificate(conn->ssl);
|
|
710
|
+
#endif
|
|
711
|
+
if(!cert) {
|
|
712
|
+
/*
|
|
713
|
+
* See if there was a failed certificate associated with this client.
|
|
714
|
+
*/
|
|
715
|
+
cert_buf = (ms_cert_buf*)SSL_get_app_data(conn->ssl);
|
|
716
|
+
if(!cert_buf) {
|
|
717
|
+
return Qnil;
|
|
718
|
+
}
|
|
719
|
+
buf = cert_buf->buf;
|
|
720
|
+
bytes = cert_buf->bytes;
|
|
721
|
+
|
|
722
|
+
} else {
|
|
723
|
+
bytes = i2d_X509(cert, &buf);
|
|
724
|
+
X509_free(cert);
|
|
725
|
+
|
|
726
|
+
if(bytes < 0) {
|
|
727
|
+
return Qnil;
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
rb_cert_buf = rb_str_new((const char*)(buf), bytes);
|
|
732
|
+
if(!cert_buf) {
|
|
733
|
+
OPENSSL_free(buf);
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
return rb_cert_buf;
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
/* @see Puma::MiniSSL::Socket#ssl_version_state
|
|
740
|
+
* @version 5.0.0
|
|
741
|
+
*/
|
|
742
|
+
static VALUE
|
|
743
|
+
engine_ssl_vers_st(VALUE self) {
|
|
744
|
+
ms_conn* conn;
|
|
745
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
|
746
|
+
return rb_ary_new3(2, rb_str_new2(SSL_get_version(conn->ssl)), rb_str_new2(SSL_state_string(conn->ssl)));
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
VALUE noop(VALUE self) {
|
|
750
|
+
return Qnil;
|
|
751
|
+
}
|
|
752
|
+
|
|
173
753
|
void Init_mini_ssl(VALUE puma) {
|
|
174
|
-
VALUE mod, eng;
|
|
754
|
+
VALUE mod, eng, sslctx;
|
|
755
|
+
|
|
756
|
+
/* Fake operation for documentation (RDoc, YARD) */
|
|
757
|
+
#if 0 == 1
|
|
758
|
+
puma = rb_define_module("Puma");
|
|
759
|
+
#endif
|
|
175
760
|
|
|
176
761
|
SSL_library_init();
|
|
177
762
|
OpenSSL_add_ssl_algorithms();
|
|
178
763
|
SSL_load_error_strings();
|
|
179
764
|
ERR_load_crypto_strings();
|
|
180
|
-
|
|
765
|
+
|
|
181
766
|
mod = rb_define_module_under(puma, "MiniSSL");
|
|
767
|
+
|
|
182
768
|
eng = rb_define_class_under(mod, "Engine", rb_cObject);
|
|
769
|
+
rb_undef_alloc_func(eng);
|
|
770
|
+
|
|
771
|
+
sslctx = rb_define_class_under(mod, "SSLContext", rb_cObject);
|
|
772
|
+
rb_define_alloc_func(sslctx, sslctx_alloc);
|
|
773
|
+
rb_define_method(sslctx, "initialize", sslctx_initialize, 1);
|
|
774
|
+
rb_undef_method(sslctx, "initialize_copy");
|
|
775
|
+
|
|
776
|
+
|
|
777
|
+
// OpenSSL Build / Runtime/Load versions
|
|
778
|
+
|
|
779
|
+
/* Version of OpenSSL that Puma was compiled with */
|
|
780
|
+
rb_define_const(mod, "OPENSSL_VERSION", rb_str_new2(OPENSSL_VERSION_TEXT));
|
|
781
|
+
|
|
782
|
+
#if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000
|
|
783
|
+
/* Version of OpenSSL that Puma loaded with */
|
|
784
|
+
rb_define_const(mod, "OPENSSL_LIBRARY_VERSION", rb_str_new2(OpenSSL_version(OPENSSL_VERSION)));
|
|
785
|
+
#else
|
|
786
|
+
rb_define_const(mod, "OPENSSL_LIBRARY_VERSION", rb_str_new2(SSLeay_version(SSLEAY_VERSION)));
|
|
787
|
+
#endif
|
|
788
|
+
|
|
789
|
+
#if defined(OPENSSL_NO_SSL3) || defined(OPENSSL_NO_SSL3_METHOD)
|
|
790
|
+
/* True if SSL3 is not available */
|
|
791
|
+
rb_define_const(mod, "OPENSSL_NO_SSL3", Qtrue);
|
|
792
|
+
#else
|
|
793
|
+
rb_define_const(mod, "OPENSSL_NO_SSL3", Qfalse);
|
|
794
|
+
#endif
|
|
795
|
+
|
|
796
|
+
#if defined(OPENSSL_NO_TLS1) || defined(OPENSSL_NO_TLS1_METHOD)
|
|
797
|
+
/* True if TLS1 is not available */
|
|
798
|
+
rb_define_const(mod, "OPENSSL_NO_TLS1", Qtrue);
|
|
799
|
+
#else
|
|
800
|
+
rb_define_const(mod, "OPENSSL_NO_TLS1", Qfalse);
|
|
801
|
+
#endif
|
|
802
|
+
|
|
803
|
+
#if defined(OPENSSL_NO_TLS1_1) || defined(OPENSSL_NO_TLS1_1_METHOD)
|
|
804
|
+
/* True if TLS1_1 is not available */
|
|
805
|
+
rb_define_const(mod, "OPENSSL_NO_TLS1_1", Qtrue);
|
|
806
|
+
#else
|
|
807
|
+
rb_define_const(mod, "OPENSSL_NO_TLS1_1", Qfalse);
|
|
808
|
+
#endif
|
|
809
|
+
|
|
810
|
+
rb_define_singleton_method(mod, "check", noop, 0);
|
|
183
811
|
|
|
184
812
|
eError = rb_define_class_under(mod, "SSLError", rb_eStandardError);
|
|
185
813
|
|
|
186
|
-
rb_define_singleton_method(eng, "server", engine_init_server,
|
|
814
|
+
rb_define_singleton_method(eng, "server", engine_init_server, 1);
|
|
187
815
|
rb_define_singleton_method(eng, "client", engine_init_client, 0);
|
|
188
816
|
|
|
189
817
|
rb_define_method(eng, "inject", engine_inject, 1);
|
|
@@ -191,4 +819,34 @@ void Init_mini_ssl(VALUE puma) {
|
|
|
191
819
|
|
|
192
820
|
rb_define_method(eng, "write", engine_write, 1);
|
|
193
821
|
rb_define_method(eng, "extract", engine_extract, 0);
|
|
822
|
+
|
|
823
|
+
rb_define_method(eng, "shutdown", engine_shutdown, 0);
|
|
824
|
+
|
|
825
|
+
rb_define_method(eng, "init?", engine_init, 0);
|
|
826
|
+
|
|
827
|
+
/* @!attribute [r] peercert
|
|
828
|
+
* Returns `nil` when `MiniSSL::Context#verify_mode` is set to `VERIFY_NONE`.
|
|
829
|
+
* @return [String, nil] DER encoded cert
|
|
830
|
+
*/
|
|
831
|
+
rb_define_method(eng, "peercert", engine_peercert, 0);
|
|
832
|
+
|
|
833
|
+
rb_define_method(eng, "ssl_vers_st", engine_ssl_vers_st, 0);
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
#else
|
|
837
|
+
|
|
838
|
+
NORETURN(VALUE raise_error(VALUE self));
|
|
839
|
+
|
|
840
|
+
VALUE raise_error(VALUE self) {
|
|
841
|
+
rb_raise(rb_eStandardError, "SSL not available in this build");
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
void Init_mini_ssl(VALUE puma) {
|
|
845
|
+
VALUE mod;
|
|
846
|
+
|
|
847
|
+
mod = rb_define_module_under(puma, "MiniSSL");
|
|
848
|
+
rb_define_class_under(mod, "SSLError", rb_eStandardError);
|
|
849
|
+
|
|
850
|
+
rb_define_singleton_method(mod, "check", raise_error, 0);
|
|
194
851
|
}
|
|
852
|
+
#endif
|