puma 3.12.6 → 6.3.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of puma might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/History.md +1806 -451
- data/LICENSE +23 -20
- data/README.md +217 -65
- data/bin/puma-wild +3 -9
- data/docs/architecture.md +59 -21
- data/docs/compile_options.md +55 -0
- data/docs/deployment.md +69 -58
- data/docs/fork_worker.md +31 -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/jungle/README.md +9 -0
- data/{tools → docs}/jungle/rc.d/README.md +1 -1
- data/{tools → docs}/jungle/rc.d/puma +2 -2
- data/docs/kubernetes.md +66 -0
- data/docs/nginx.md +2 -2
- data/docs/plugins.md +22 -12
- data/docs/rails_dev_mode.md +28 -0
- data/docs/restart.md +47 -22
- data/docs/signals.md +13 -11
- data/docs/stats.md +142 -0
- data/docs/systemd.md +94 -120
- 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/ext_help.h +1 -1
- data/ext/puma_http11/extconf.rb +61 -3
- data/ext/puma_http11/http11_parser.c +103 -117
- data/ext/puma_http11/http11_parser.h +2 -2
- data/ext/puma_http11/http11_parser.java.rl +22 -38
- data/ext/puma_http11/http11_parser.rl +3 -3
- data/ext/puma_http11/http11_parser_common.rl +6 -6
- data/ext/puma_http11/mini_ssl.c +389 -99
- data/ext/puma_http11/no_ssl/PumaHttp11Service.java +15 -0
- data/ext/puma_http11/org/jruby/puma/Http11.java +108 -116
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +84 -99
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +248 -92
- data/ext/puma_http11/puma_http11.c +49 -57
- data/lib/puma/app/status.rb +71 -49
- data/lib/puma/binder.rb +244 -150
- data/lib/puma/cli.rb +38 -34
- data/lib/puma/client.rb +388 -244
- data/lib/puma/cluster/worker.rb +180 -0
- data/lib/puma/cluster/worker_handle.rb +97 -0
- data/lib/puma/cluster.rb +261 -243
- data/lib/puma/commonlogger.rb +21 -14
- data/lib/puma/configuration.rb +116 -88
- data/lib/puma/const.rb +154 -104
- data/lib/puma/control_cli.rb +115 -70
- data/lib/puma/detect.rb +33 -2
- data/lib/puma/dsl.rb +764 -134
- data/lib/puma/error_logger.rb +113 -0
- data/lib/puma/events.rb +16 -112
- data/lib/puma/io_buffer.rb +42 -5
- data/lib/puma/jruby_restart.rb +2 -59
- data/lib/puma/json_serialization.rb +96 -0
- data/lib/puma/launcher/bundle_pruner.rb +104 -0
- data/lib/puma/launcher.rb +184 -133
- data/lib/puma/log_writer.rb +147 -0
- data/lib/puma/minissl/context_builder.rb +93 -0
- data/lib/puma/minissl.rb +263 -70
- data/lib/puma/null_io.rb +18 -1
- data/lib/puma/plugin/systemd.rb +90 -0
- data/lib/puma/plugin/tmp_restart.rb +3 -1
- data/lib/puma/plugin.rb +7 -13
- data/lib/puma/rack/builder.rb +9 -11
- data/lib/puma/rack/urlmap.rb +2 -0
- data/lib/puma/rack_default.rb +21 -4
- data/lib/puma/reactor.rb +93 -315
- data/lib/puma/request.rb +671 -0
- data/lib/puma/runner.rb +94 -69
- data/lib/puma/sd_notify.rb +149 -0
- data/lib/puma/server.rb +327 -772
- data/lib/puma/single.rb +20 -74
- data/lib/puma/state_file.rb +45 -8
- data/lib/puma/thread_pool.rb +146 -92
- data/lib/puma/util.rb +22 -10
- data/lib/puma.rb +60 -5
- data/lib/rack/handler/puma.rb +116 -90
- data/tools/Dockerfile +16 -0
- data/tools/trickletest.rb +0 -1
- metadata +54 -32
- data/ext/puma_http11/io_buffer.c +0 -155
- data/lib/puma/accept_nonblock.rb +0 -23
- data/lib/puma/compat.rb +0 -14
- data/lib/puma/convenient.rb +0 -25
- data/lib/puma/daemon_ext.rb +0 -33
- data/lib/puma/delegation.rb +0 -13
- data/lib/puma/java_io_buffer.rb +0 -47
- data/lib/puma/rack/backports/uri/common_193.rb +0 -33
- data/lib/puma/tcp_logger.rb +0 -41
- data/tools/jungle/README.md +0 -19
- data/tools/jungle/init.d/README.md +0 -61
- data/tools/jungle/init.d/puma +0 -421
- data/tools/jungle/init.d/run-puma +0 -18
- data/tools/jungle/upstart/README.md +0 -61
- data/tools/jungle/upstart/puma-manager.conf +0 -31
- data/tools/jungle/upstart/puma.conf +0 -69
- /data/{tools → docs}/jungle/rc.d/puma.conf +0 -0
data/ext/puma_http11/mini_ssl.c
CHANGED
@@ -2,12 +2,7 @@
|
|
2
2
|
|
3
3
|
#include <ruby.h>
|
4
4
|
#include <ruby/version.h>
|
5
|
-
|
6
|
-
#if RUBY_API_VERSION_MAJOR == 1
|
7
|
-
#include <rubyio.h>
|
8
|
-
#else
|
9
5
|
#include <ruby/io.h>
|
10
|
-
#endif
|
11
6
|
|
12
7
|
#ifdef HAVE_OPENSSL_BIO_H
|
13
8
|
|
@@ -33,7 +28,16 @@ typedef struct {
|
|
33
28
|
int bytes;
|
34
29
|
} ms_cert_buf;
|
35
30
|
|
36
|
-
|
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
|
+
void engine_free(void *ptr) {
|
40
|
+
ms_conn *conn = ptr;
|
37
41
|
ms_cert_buf* cert_buf = (ms_cert_buf*)SSL_get_app_data(conn->ssl);
|
38
42
|
if(cert_buf) {
|
39
43
|
OPENSSL_free(cert_buf->buf);
|
@@ -45,61 +49,72 @@ void engine_free(ms_conn* conn) {
|
|
45
49
|
free(conn);
|
46
50
|
}
|
47
51
|
|
48
|
-
|
49
|
-
|
52
|
+
const rb_data_type_t engine_data_type = {
|
53
|
+
"MiniSSL/ENGINE",
|
54
|
+
{ 0, engine_free, 0 },
|
55
|
+
0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
|
56
|
+
};
|
50
57
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
BIO_set_nbio(conn->read, 1);
|
55
|
-
|
56
|
-
conn->write = BIO_new(BIO_s_mem());
|
57
|
-
BIO_set_nbio(conn->write, 1);
|
58
|
-
|
59
|
-
conn->ssl = 0;
|
60
|
-
conn->ctx = 0;
|
61
|
-
|
62
|
-
return conn;
|
63
|
-
}
|
64
|
-
|
65
|
-
DH *get_dh1024() {
|
66
|
-
/* `openssl dhparam 1024 -C`
|
58
|
+
#ifndef HAVE_SSL_CTX_SET_DH_AUTO
|
59
|
+
DH *get_dh2048(void) {
|
60
|
+
/* `openssl dhparam -C 2048`
|
67
61
|
* -----BEGIN DH PARAMETERS-----
|
68
|
-
*
|
69
|
-
*
|
70
|
-
*
|
62
|
+
* MIIBCAKCAQEAjmh1uQHdTfxOyxEbKAV30fUfzqMDF/ChPzjfyzl2jcrqQMhrk76o
|
63
|
+
* 2NPNXqxHwsddMZ1RzvU8/jl+uhRuPWjXCFZbhET4N1vrviZM3VJhV8PPHuiVOACO
|
64
|
+
* y32jFd+Szx4bo2cXSK83hJ6jRd+0asP1awWjz9/06dFkrILCXMIfQLo0D8rqmppn
|
65
|
+
* EfDDAwuudCpM9kcDmBRAm9JsKbQ6gzZWjkc5+QWSaQofojIHbjvj3xzguaCJn+oQ
|
66
|
+
* vHWM+hsAnaOgEwCyeZ3xqs+/5lwSbkE/tqJW98cEZGygBUVo9jxZRZx6KOfjpdrb
|
67
|
+
* yenO9LJr/qtyrZB31WJbqxI0m0AKTAO8UwIBAg==
|
71
68
|
* -----END DH PARAMETERS-----
|
72
69
|
*/
|
73
|
-
static unsigned char
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
70
|
+
static unsigned char dh2048_p[] = {
|
71
|
+
0x8E, 0x68, 0x75, 0xB9, 0x01, 0xDD, 0x4D, 0xFC, 0x4E, 0xCB,
|
72
|
+
0x11, 0x1B, 0x28, 0x05, 0x77, 0xD1, 0xF5, 0x1F, 0xCE, 0xA3,
|
73
|
+
0x03, 0x17, 0xF0, 0xA1, 0x3F, 0x38, 0xDF, 0xCB, 0x39, 0x76,
|
74
|
+
0x8D, 0xCA, 0xEA, 0x40, 0xC8, 0x6B, 0x93, 0xBE, 0xA8, 0xD8,
|
75
|
+
0xD3, 0xCD, 0x5E, 0xAC, 0x47, 0xC2, 0xC7, 0x5D, 0x31, 0x9D,
|
76
|
+
0x51, 0xCE, 0xF5, 0x3C, 0xFE, 0x39, 0x7E, 0xBA, 0x14, 0x6E,
|
77
|
+
0x3D, 0x68, 0xD7, 0x08, 0x56, 0x5B, 0x84, 0x44, 0xF8, 0x37,
|
78
|
+
0x5B, 0xEB, 0xBE, 0x26, 0x4C, 0xDD, 0x52, 0x61, 0x57, 0xC3,
|
79
|
+
0xCF, 0x1E, 0xE8, 0x95, 0x38, 0x00, 0x8E, 0xCB, 0x7D, 0xA3,
|
80
|
+
0x15, 0xDF, 0x92, 0xCF, 0x1E, 0x1B, 0xA3, 0x67, 0x17, 0x48,
|
81
|
+
0xAF, 0x37, 0x84, 0x9E, 0xA3, 0x45, 0xDF, 0xB4, 0x6A, 0xC3,
|
82
|
+
0xF5, 0x6B, 0x05, 0xA3, 0xCF, 0xDF, 0xF4, 0xE9, 0xD1, 0x64,
|
83
|
+
0xAC, 0x82, 0xC2, 0x5C, 0xC2, 0x1F, 0x40, 0xBA, 0x34, 0x0F,
|
84
|
+
0xCA, 0xEA, 0x9A, 0x9A, 0x67, 0x11, 0xF0, 0xC3, 0x03, 0x0B,
|
85
|
+
0xAE, 0x74, 0x2A, 0x4C, 0xF6, 0x47, 0x03, 0x98, 0x14, 0x40,
|
86
|
+
0x9B, 0xD2, 0x6C, 0x29, 0xB4, 0x3A, 0x83, 0x36, 0x56, 0x8E,
|
87
|
+
0x47, 0x39, 0xF9, 0x05, 0x92, 0x69, 0x0A, 0x1F, 0xA2, 0x32,
|
88
|
+
0x07, 0x6E, 0x3B, 0xE3, 0xDF, 0x1C, 0xE0, 0xB9, 0xA0, 0x89,
|
89
|
+
0x9F, 0xEA, 0x10, 0xBC, 0x75, 0x8C, 0xFA, 0x1B, 0x00, 0x9D,
|
90
|
+
0xA3, 0xA0, 0x13, 0x00, 0xB2, 0x79, 0x9D, 0xF1, 0xAA, 0xCF,
|
91
|
+
0xBF, 0xE6, 0x5C, 0x12, 0x6E, 0x41, 0x3F, 0xB6, 0xA2, 0x56,
|
92
|
+
0xF7, 0xC7, 0x04, 0x64, 0x6C, 0xA0, 0x05, 0x45, 0x68, 0xF6,
|
93
|
+
0x3C, 0x59, 0x45, 0x9C, 0x7A, 0x28, 0xE7, 0xE3, 0xA5, 0xDA,
|
94
|
+
0xDB, 0xC9, 0xE9, 0xCE, 0xF4, 0xB2, 0x6B, 0xFE, 0xAB, 0x72,
|
95
|
+
0xAD, 0x90, 0x77, 0xD5, 0x62, 0x5B, 0xAB, 0x12, 0x34, 0x9B,
|
96
|
+
0x40, 0x0A, 0x4C, 0x03, 0xBC, 0x53
|
85
97
|
};
|
86
|
-
static unsigned char
|
98
|
+
static unsigned char dh2048_g[] = { 0x02 };
|
87
99
|
|
88
100
|
DH *dh;
|
101
|
+
#if !(OPENSSL_VERSION_NUMBER < 0x10100005L)
|
102
|
+
BIGNUM *p, *g;
|
103
|
+
#endif
|
104
|
+
|
89
105
|
dh = DH_new();
|
90
106
|
|
91
|
-
#if OPENSSL_VERSION_NUMBER < 0x10100005L
|
92
|
-
dh->p = BN_bin2bn(
|
93
|
-
dh->g = BN_bin2bn(
|
107
|
+
#if OPENSSL_VERSION_NUMBER < 0x10100005L
|
108
|
+
dh->p = BN_bin2bn(dh2048_p, sizeof(dh2048_p), NULL);
|
109
|
+
dh->g = BN_bin2bn(dh2048_g, sizeof(dh2048_g), NULL);
|
94
110
|
|
95
111
|
if ((dh->p == NULL) || (dh->g == NULL)) {
|
96
112
|
DH_free(dh);
|
97
113
|
return NULL;
|
98
114
|
}
|
99
115
|
#else
|
100
|
-
|
101
|
-
|
102
|
-
g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
|
116
|
+
p = BN_bin2bn(dh2048_p, sizeof(dh2048_p), NULL);
|
117
|
+
g = BN_bin2bn(dh2048_g, sizeof(dh2048_g), NULL);
|
103
118
|
|
104
119
|
if (p == NULL || g == NULL || !DH_set0_pqg(dh, p, NULL, g)) {
|
105
120
|
DH_free(dh);
|
@@ -111,6 +126,38 @@ DH *get_dh1024() {
|
|
111
126
|
|
112
127
|
return dh;
|
113
128
|
}
|
129
|
+
#endif
|
130
|
+
|
131
|
+
static void
|
132
|
+
sslctx_free(void *ptr) {
|
133
|
+
SSL_CTX *ctx = ptr;
|
134
|
+
SSL_CTX_free(ctx);
|
135
|
+
}
|
136
|
+
|
137
|
+
static const rb_data_type_t sslctx_type = {
|
138
|
+
"MiniSSL/SSLContext",
|
139
|
+
{
|
140
|
+
0, sslctx_free,
|
141
|
+
},
|
142
|
+
0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
|
143
|
+
};
|
144
|
+
|
145
|
+
ms_conn* engine_alloc(VALUE klass, VALUE* obj) {
|
146
|
+
ms_conn* conn;
|
147
|
+
|
148
|
+
*obj = TypedData_Make_Struct(klass, ms_conn, &engine_data_type, conn);
|
149
|
+
|
150
|
+
conn->read = BIO_new(BIO_s_mem());
|
151
|
+
BIO_set_nbio(conn->read, 1);
|
152
|
+
|
153
|
+
conn->write = BIO_new(BIO_s_mem());
|
154
|
+
BIO_set_nbio(conn->write, 1);
|
155
|
+
|
156
|
+
conn->ssl = 0;
|
157
|
+
conn->ctx = 0;
|
158
|
+
|
159
|
+
return conn;
|
160
|
+
}
|
114
161
|
|
115
162
|
static int engine_verify_callback(int preverify_ok, X509_STORE_CTX* ctx) {
|
116
163
|
X509* err_cert;
|
@@ -138,45 +185,201 @@ static int engine_verify_callback(int preverify_ok, X509_STORE_CTX* ctx) {
|
|
138
185
|
return preverify_ok;
|
139
186
|
}
|
140
187
|
|
141
|
-
|
142
|
-
|
188
|
+
static int password_callback(char *buf, int size, int rwflag, void *userdata) {
|
189
|
+
const char *password = (const char *) userdata;
|
190
|
+
size_t len = strlen(password);
|
191
|
+
|
192
|
+
if (len > (size_t) size) {
|
193
|
+
return 0;
|
194
|
+
}
|
195
|
+
|
196
|
+
memcpy(buf, password, len);
|
197
|
+
return (int) len;
|
198
|
+
}
|
199
|
+
|
200
|
+
static VALUE
|
201
|
+
sslctx_alloc(VALUE klass) {
|
202
|
+
SSL_CTX *ctx;
|
203
|
+
long mode = 0 |
|
204
|
+
SSL_MODE_ENABLE_PARTIAL_WRITE |
|
205
|
+
SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
|
206
|
+
SSL_MODE_RELEASE_BUFFERS;
|
207
|
+
|
208
|
+
#ifdef HAVE_TLS_SERVER_METHOD
|
209
|
+
ctx = SSL_CTX_new(TLS_method());
|
210
|
+
// printf("\nctx using TLS_method security_level %d\n", SSL_CTX_get_security_level(ctx));
|
211
|
+
#else
|
212
|
+
ctx = SSL_CTX_new(SSLv23_method());
|
213
|
+
#endif
|
214
|
+
if (!ctx) {
|
215
|
+
rb_raise(eError, "SSL_CTX_new");
|
216
|
+
}
|
217
|
+
SSL_CTX_set_mode(ctx, mode);
|
218
|
+
|
219
|
+
return TypedData_Wrap_Struct(klass, &sslctx_type, ctx);
|
220
|
+
}
|
221
|
+
|
222
|
+
VALUE
|
223
|
+
sslctx_initialize(VALUE self, VALUE mini_ssl_ctx) {
|
143
224
|
SSL_CTX* ctx;
|
144
|
-
|
225
|
+
int ssl_options;
|
226
|
+
VALUE key, cert, ca, verify_mode, ssl_cipher_filter, no_tlsv1, no_tlsv1_1,
|
227
|
+
verification_flags, session_id_bytes, cert_pem, key_pem, key_password_command, key_password;
|
228
|
+
BIO *bio;
|
229
|
+
X509 *x509;
|
230
|
+
EVP_PKEY *pkey;
|
231
|
+
pem_password_cb *password_cb = NULL;
|
232
|
+
const char *password = NULL;
|
233
|
+
#ifdef HAVE_SSL_CTX_SET_MIN_PROTO_VERSION
|
234
|
+
int min;
|
235
|
+
#endif
|
236
|
+
#ifndef HAVE_SSL_CTX_SET_DH_AUTO
|
237
|
+
DH *dh;
|
238
|
+
#endif
|
239
|
+
#if OPENSSL_VERSION_NUMBER < 0x10002000L
|
240
|
+
EC_KEY *ecdh;
|
241
|
+
#endif
|
242
|
+
#ifdef HAVE_SSL_CTX_SET_SESSION_CACHE_MODE
|
243
|
+
VALUE reuse, reuse_cache_size, reuse_timeout;
|
244
|
+
|
245
|
+
reuse = rb_funcall(mini_ssl_ctx, rb_intern_const("reuse"), 0);
|
246
|
+
reuse_cache_size = rb_funcall(mini_ssl_ctx, rb_intern_const("reuse_cache_size"), 0);
|
247
|
+
reuse_timeout = rb_funcall(mini_ssl_ctx, rb_intern_const("reuse_timeout"), 0);
|
248
|
+
#endif
|
249
|
+
|
250
|
+
key = rb_funcall(mini_ssl_ctx, rb_intern_const("key"), 0);
|
251
|
+
|
252
|
+
key_password_command = rb_funcall(mini_ssl_ctx, rb_intern_const("key_password_command"), 0);
|
253
|
+
|
254
|
+
cert = rb_funcall(mini_ssl_ctx, rb_intern_const("cert"), 0);
|
255
|
+
|
256
|
+
ca = rb_funcall(mini_ssl_ctx, rb_intern_const("ca"), 0);
|
257
|
+
|
258
|
+
cert_pem = rb_funcall(mini_ssl_ctx, rb_intern_const("cert_pem"), 0);
|
259
|
+
|
260
|
+
key_pem = rb_funcall(mini_ssl_ctx, rb_intern_const("key_pem"), 0);
|
145
261
|
|
146
|
-
|
262
|
+
verify_mode = rb_funcall(mini_ssl_ctx, rb_intern_const("verify_mode"), 0);
|
147
263
|
|
148
|
-
|
149
|
-
|
264
|
+
ssl_cipher_filter = rb_funcall(mini_ssl_ctx, rb_intern_const("ssl_cipher_filter"), 0);
|
265
|
+
|
266
|
+
no_tlsv1 = rb_funcall(mini_ssl_ctx, rb_intern_const("no_tlsv1"), 0);
|
267
|
+
|
268
|
+
no_tlsv1_1 = rb_funcall(mini_ssl_ctx, rb_intern_const("no_tlsv1_1"), 0);
|
269
|
+
|
270
|
+
TypedData_Get_Struct(self, SSL_CTX, &sslctx_type, ctx);
|
271
|
+
|
272
|
+
if (!NIL_P(cert)) {
|
273
|
+
StringValue(cert);
|
274
|
+
|
275
|
+
if (SSL_CTX_use_certificate_chain_file(ctx, RSTRING_PTR(cert)) != 1) {
|
276
|
+
raise_file_error("SSL_CTX_use_certificate_chain_file", RSTRING_PTR(cert));
|
277
|
+
}
|
278
|
+
}
|
279
|
+
|
280
|
+
if (!NIL_P(key_password_command)) {
|
281
|
+
key_password = rb_funcall(mini_ssl_ctx, rb_intern_const("key_password"), 0);
|
282
|
+
|
283
|
+
if (!NIL_P(key_password)) {
|
284
|
+
StringValue(key_password);
|
285
|
+
password_cb = password_callback;
|
286
|
+
password = RSTRING_PTR(key_password);
|
287
|
+
SSL_CTX_set_default_passwd_cb(ctx, password_cb);
|
288
|
+
SSL_CTX_set_default_passwd_cb_userdata(ctx, (void *) password);
|
289
|
+
}
|
290
|
+
}
|
150
291
|
|
151
|
-
|
292
|
+
if (!NIL_P(key)) {
|
293
|
+
StringValue(key);
|
152
294
|
|
153
|
-
|
154
|
-
|
295
|
+
if (SSL_CTX_use_PrivateKey_file(ctx, RSTRING_PTR(key), SSL_FILETYPE_PEM) != 1) {
|
296
|
+
raise_file_error("SSL_CTX_use_PrivateKey_file", RSTRING_PTR(key));
|
297
|
+
}
|
298
|
+
}
|
155
299
|
|
156
|
-
|
300
|
+
if (!NIL_P(cert_pem)) {
|
301
|
+
bio = BIO_new(BIO_s_mem());
|
302
|
+
BIO_puts(bio, RSTRING_PTR(cert_pem));
|
303
|
+
x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
|
157
304
|
|
158
|
-
|
159
|
-
|
305
|
+
if (SSL_CTX_use_certificate(ctx, x509) != 1) {
|
306
|
+
BIO_free(bio);
|
307
|
+
raise_file_error("SSL_CTX_use_certificate", RSTRING_PTR(cert_pem));
|
308
|
+
}
|
309
|
+
X509_free(x509);
|
310
|
+
BIO_free(bio);
|
311
|
+
}
|
160
312
|
|
161
|
-
|
162
|
-
|
313
|
+
if (!NIL_P(key_pem)) {
|
314
|
+
bio = BIO_new(BIO_s_mem());
|
315
|
+
BIO_puts(bio, RSTRING_PTR(key_pem));
|
316
|
+
pkey = PEM_read_bio_PrivateKey(bio, NULL, password_cb, (void *) password);
|
163
317
|
|
164
|
-
|
165
|
-
|
318
|
+
if (SSL_CTX_use_PrivateKey(ctx, pkey) != 1) {
|
319
|
+
BIO_free(bio);
|
320
|
+
raise_file_error("SSL_CTX_use_PrivateKey", RSTRING_PTR(key_pem));
|
321
|
+
}
|
322
|
+
EVP_PKEY_free(pkey);
|
323
|
+
BIO_free(bio);
|
324
|
+
}
|
166
325
|
|
167
|
-
|
168
|
-
conn->ctx = ctx;
|
326
|
+
verification_flags = rb_funcall(mini_ssl_ctx, rb_intern_const("verification_flags"), 0);
|
169
327
|
|
170
|
-
|
171
|
-
|
328
|
+
if (!NIL_P(verification_flags)) {
|
329
|
+
X509_VERIFY_PARAM *param = SSL_CTX_get0_param(ctx);
|
330
|
+
X509_VERIFY_PARAM_set_flags(param, NUM2INT(verification_flags));
|
331
|
+
SSL_CTX_set1_param(ctx, param);
|
332
|
+
}
|
172
333
|
|
173
334
|
if (!NIL_P(ca)) {
|
174
335
|
StringValue(ca);
|
175
|
-
SSL_CTX_load_verify_locations(ctx, RSTRING_PTR(ca), NULL)
|
336
|
+
if (SSL_CTX_load_verify_locations(ctx, RSTRING_PTR(ca), NULL) != 1) {
|
337
|
+
raise_file_error("SSL_CTX_load_verify_locations", RSTRING_PTR(ca));
|
338
|
+
}
|
176
339
|
}
|
177
340
|
|
178
|
-
|
179
|
-
|
341
|
+
ssl_options = SSL_OP_CIPHER_SERVER_PREFERENCE | SSL_OP_SINGLE_ECDH_USE | SSL_OP_NO_COMPRESSION;
|
342
|
+
|
343
|
+
#ifdef HAVE_SSL_CTX_SET_MIN_PROTO_VERSION
|
344
|
+
if (RTEST(no_tlsv1_1)) {
|
345
|
+
min = TLS1_2_VERSION;
|
346
|
+
}
|
347
|
+
else if (RTEST(no_tlsv1)) {
|
348
|
+
min = TLS1_1_VERSION;
|
349
|
+
}
|
350
|
+
else {
|
351
|
+
min = TLS1_VERSION;
|
352
|
+
}
|
353
|
+
|
354
|
+
SSL_CTX_set_min_proto_version(ctx, min);
|
355
|
+
|
356
|
+
#else
|
357
|
+
/* As of 1.0.2f, SSL_OP_SINGLE_DH_USE key use is always on */
|
358
|
+
ssl_options |= SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_SINGLE_DH_USE;
|
359
|
+
|
360
|
+
if (RTEST(no_tlsv1)) {
|
361
|
+
ssl_options |= SSL_OP_NO_TLSv1;
|
362
|
+
}
|
363
|
+
if(RTEST(no_tlsv1_1)) {
|
364
|
+
ssl_options |= SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1;
|
365
|
+
}
|
366
|
+
#endif
|
367
|
+
|
368
|
+
#ifdef HAVE_SSL_CTX_SET_SESSION_CACHE_MODE
|
369
|
+
if (!NIL_P(reuse)) {
|
370
|
+
SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER);
|
371
|
+
if (!NIL_P(reuse_cache_size)) {
|
372
|
+
SSL_CTX_sess_set_cache_size(ctx, NUM2INT(reuse_cache_size));
|
373
|
+
}
|
374
|
+
if (!NIL_P(reuse_timeout)) {
|
375
|
+
SSL_CTX_set_timeout(ctx, NUM2INT(reuse_timeout));
|
376
|
+
}
|
377
|
+
} else {
|
378
|
+
SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
|
379
|
+
}
|
380
|
+
#endif
|
381
|
+
|
382
|
+
SSL_CTX_set_options(ctx, ssl_options);
|
180
383
|
|
181
384
|
if (!NIL_P(ssl_cipher_filter)) {
|
182
385
|
StringValue(ssl_cipher_filter);
|
@@ -186,29 +389,65 @@ VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) {
|
|
186
389
|
SSL_CTX_set_cipher_list(ctx, "HIGH:!aNULL@STRENGTH");
|
187
390
|
}
|
188
391
|
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
#ifndef OPENSSL_NO_ECDH
|
193
|
-
EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_secp521r1);
|
392
|
+
#if OPENSSL_VERSION_NUMBER < 0x10002000L
|
393
|
+
// Remove this case if OpenSSL 1.0.1 (now EOL) support is no longer needed.
|
394
|
+
ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
|
194
395
|
if (ecdh) {
|
195
396
|
SSL_CTX_set_tmp_ecdh(ctx, ecdh);
|
196
397
|
EC_KEY_free(ecdh);
|
197
398
|
}
|
399
|
+
#elif OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
|
400
|
+
SSL_CTX_set_ecdh_auto(ctx, 1);
|
198
401
|
#endif
|
199
402
|
|
200
|
-
ssl = SSL_new(ctx);
|
201
|
-
conn->ssl = ssl;
|
202
|
-
SSL_set_app_data(ssl, NULL);
|
203
|
-
|
204
403
|
if (NIL_P(verify_mode)) {
|
205
|
-
/*
|
404
|
+
/* SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); */
|
206
405
|
} else {
|
207
|
-
|
406
|
+
SSL_CTX_set_verify(ctx, NUM2INT(verify_mode), engine_verify_callback);
|
208
407
|
}
|
209
408
|
|
210
|
-
|
409
|
+
// Random.bytes available in Ruby 2.5 and later, Random::DEFAULT deprecated in 3.0
|
410
|
+
session_id_bytes = rb_funcall(
|
411
|
+
#ifdef HAVE_RANDOM_BYTES
|
412
|
+
rb_cRandom,
|
413
|
+
#else
|
414
|
+
rb_const_get(rb_cRandom, rb_intern_const("DEFAULT")),
|
415
|
+
#endif
|
416
|
+
rb_intern_const("bytes"),
|
417
|
+
1, ULL2NUM(SSL_MAX_SSL_SESSION_ID_LENGTH));
|
418
|
+
|
419
|
+
SSL_CTX_set_session_id_context(ctx,
|
420
|
+
(unsigned char *) RSTRING_PTR(session_id_bytes),
|
421
|
+
SSL_MAX_SSL_SESSION_ID_LENGTH);
|
422
|
+
|
423
|
+
// printf("\ninitialize end security_level %d\n", SSL_CTX_get_security_level(ctx));
|
211
424
|
|
425
|
+
#ifdef HAVE_SSL_CTX_SET_DH_AUTO
|
426
|
+
// https://www.openssl.org/docs/man3.0/man3/SSL_CTX_set_dh_auto.html
|
427
|
+
SSL_CTX_set_dh_auto(ctx, 1);
|
428
|
+
#else
|
429
|
+
dh = get_dh2048();
|
430
|
+
SSL_CTX_set_tmp_dh(ctx, dh);
|
431
|
+
#endif
|
432
|
+
|
433
|
+
rb_obj_freeze(self);
|
434
|
+
return self;
|
435
|
+
}
|
436
|
+
|
437
|
+
VALUE engine_init_server(VALUE self, VALUE sslctx) {
|
438
|
+
ms_conn* conn;
|
439
|
+
VALUE obj;
|
440
|
+
SSL_CTX* ctx;
|
441
|
+
SSL* ssl;
|
442
|
+
|
443
|
+
conn = engine_alloc(self, &obj);
|
444
|
+
|
445
|
+
TypedData_Get_Struct(sslctx, SSL_CTX, &sslctx_type, ctx);
|
446
|
+
|
447
|
+
ssl = SSL_new(ctx);
|
448
|
+
conn->ssl = ssl;
|
449
|
+
SSL_set_app_data(ssl, NULL);
|
450
|
+
SSL_set_bio(ssl, conn->read, conn->write);
|
212
451
|
SSL_set_accept_state(ssl);
|
213
452
|
return obj;
|
214
453
|
}
|
@@ -216,8 +455,11 @@ VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) {
|
|
216
455
|
VALUE engine_init_client(VALUE klass) {
|
217
456
|
VALUE obj;
|
218
457
|
ms_conn* conn = engine_alloc(klass, &obj);
|
219
|
-
|
458
|
+
#ifdef HAVE_DTLS_METHOD
|
459
|
+
conn->ctx = SSL_CTX_new(DTLS_method());
|
460
|
+
#else
|
220
461
|
conn->ctx = SSL_CTX_new(DTLSv1_method());
|
462
|
+
#endif
|
221
463
|
conn->ssl = SSL_new(conn->ctx);
|
222
464
|
SSL_set_app_data(conn->ssl, NULL);
|
223
465
|
SSL_set_verify(conn->ssl, SSL_VERIFY_NONE, NULL);
|
@@ -232,7 +474,7 @@ VALUE engine_inject(VALUE self, VALUE str) {
|
|
232
474
|
ms_conn* conn;
|
233
475
|
long used;
|
234
476
|
|
235
|
-
|
477
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
236
478
|
|
237
479
|
StringValue(str);
|
238
480
|
|
@@ -245,13 +487,14 @@ VALUE engine_inject(VALUE self, VALUE str) {
|
|
245
487
|
return INT2FIX(used);
|
246
488
|
}
|
247
489
|
|
248
|
-
|
490
|
+
NORETURN(void raise_error(SSL* ssl, int result));
|
249
491
|
|
250
492
|
void raise_error(SSL* ssl, int result) {
|
251
493
|
char buf[512];
|
252
494
|
char msg[512];
|
253
495
|
const char* err_str;
|
254
496
|
int err = errno;
|
497
|
+
int mask = 4095;
|
255
498
|
int ssl_err = SSL_get_error(ssl, result);
|
256
499
|
int verify_err = (int) SSL_get_verify_result(ssl);
|
257
500
|
|
@@ -268,8 +511,7 @@ void raise_error(SSL* ssl, int result) {
|
|
268
511
|
} else {
|
269
512
|
err = (int) ERR_get_error();
|
270
513
|
ERR_error_string_n(err, buf, sizeof(buf));
|
271
|
-
snprintf(msg, sizeof(msg), "OpenSSL error: %s - %d", buf, err);
|
272
|
-
|
514
|
+
snprintf(msg, sizeof(msg), "OpenSSL error: %s - %d", buf, err & mask);
|
273
515
|
}
|
274
516
|
} else {
|
275
517
|
snprintf(msg, sizeof(msg), "Unknown OpenSSL error: %d", ssl_err);
|
@@ -284,7 +526,7 @@ VALUE engine_read(VALUE self) {
|
|
284
526
|
char buf[512];
|
285
527
|
int bytes, error;
|
286
528
|
|
287
|
-
|
529
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
288
530
|
|
289
531
|
ERR_clear_error();
|
290
532
|
|
@@ -311,7 +553,7 @@ VALUE engine_write(VALUE self, VALUE str) {
|
|
311
553
|
ms_conn* conn;
|
312
554
|
int bytes;
|
313
555
|
|
314
|
-
|
556
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
315
557
|
|
316
558
|
StringValue(str);
|
317
559
|
|
@@ -333,9 +575,11 @@ VALUE engine_extract(VALUE self) {
|
|
333
575
|
ms_conn* conn;
|
334
576
|
int bytes;
|
335
577
|
size_t pending;
|
336
|
-
|
578
|
+
// https://www.openssl.org/docs/manmaster/man3/BIO_f_buffer.html
|
579
|
+
// crypto/bio/bf_buff.c DEFAULT_BUFFER_SIZE
|
580
|
+
char buf[4096];
|
337
581
|
|
338
|
-
|
582
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
339
583
|
|
340
584
|
pending = BIO_pending(conn->write);
|
341
585
|
if(pending > 0) {
|
@@ -354,7 +598,7 @@ VALUE engine_shutdown(VALUE self) {
|
|
354
598
|
ms_conn* conn;
|
355
599
|
int ok;
|
356
600
|
|
357
|
-
|
601
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
358
602
|
|
359
603
|
ERR_clear_error();
|
360
604
|
|
@@ -369,7 +613,7 @@ VALUE engine_shutdown(VALUE self) {
|
|
369
613
|
VALUE engine_init(VALUE self) {
|
370
614
|
ms_conn* conn;
|
371
615
|
|
372
|
-
|
616
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
373
617
|
|
374
618
|
return SSL_in_init(conn->ssl) ? Qtrue : Qfalse;
|
375
619
|
}
|
@@ -382,9 +626,13 @@ VALUE engine_peercert(VALUE self) {
|
|
382
626
|
ms_cert_buf* cert_buf = NULL;
|
383
627
|
VALUE rb_cert_buf;
|
384
628
|
|
385
|
-
|
629
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
386
630
|
|
631
|
+
#ifdef HAVE_SSL_GET1_PEER_CERTIFICATE
|
632
|
+
cert = SSL_get1_peer_certificate(conn->ssl);
|
633
|
+
#else
|
387
634
|
cert = SSL_get_peer_certificate(conn->ssl);
|
635
|
+
#endif
|
388
636
|
if(!cert) {
|
389
637
|
/*
|
390
638
|
* See if there was a failed certificate associated with this client.
|
@@ -413,12 +661,22 @@ VALUE engine_peercert(VALUE self) {
|
|
413
661
|
return rb_cert_buf;
|
414
662
|
}
|
415
663
|
|
664
|
+
/* @see Puma::MiniSSL::Socket#ssl_version_state
|
665
|
+
* @version 5.0.0
|
666
|
+
*/
|
667
|
+
static VALUE
|
668
|
+
engine_ssl_vers_st(VALUE self) {
|
669
|
+
ms_conn* conn;
|
670
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
671
|
+
return rb_ary_new3(2, rb_str_new2(SSL_get_version(conn->ssl)), rb_str_new2(SSL_state_string(conn->ssl)));
|
672
|
+
}
|
673
|
+
|
416
674
|
VALUE noop(VALUE self) {
|
417
675
|
return Qnil;
|
418
676
|
}
|
419
677
|
|
420
678
|
void Init_mini_ssl(VALUE puma) {
|
421
|
-
VALUE mod, eng;
|
679
|
+
VALUE mod, eng, sslctx;
|
422
680
|
|
423
681
|
/* Fake operation for documentation (RDoc, YARD) */
|
424
682
|
#if 0 == 1
|
@@ -431,18 +689,47 @@ void Init_mini_ssl(VALUE puma) {
|
|
431
689
|
ERR_load_crypto_strings();
|
432
690
|
|
433
691
|
mod = rb_define_module_under(puma, "MiniSSL");
|
692
|
+
|
434
693
|
eng = rb_define_class_under(mod, "Engine", rb_cObject);
|
694
|
+
rb_undef_alloc_func(eng);
|
695
|
+
|
696
|
+
sslctx = rb_define_class_under(mod, "SSLContext", rb_cObject);
|
697
|
+
rb_define_alloc_func(sslctx, sslctx_alloc);
|
698
|
+
rb_define_method(sslctx, "initialize", sslctx_initialize, 1);
|
699
|
+
rb_undef_method(sslctx, "initialize_copy");
|
700
|
+
|
435
701
|
|
436
702
|
// OpenSSL Build / Runtime/Load versions
|
437
703
|
|
438
704
|
/* Version of OpenSSL that Puma was compiled with */
|
439
|
-
|
705
|
+
rb_define_const(mod, "OPENSSL_VERSION", rb_str_new2(OPENSSL_VERSION_TEXT));
|
440
706
|
|
441
707
|
#if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000
|
442
|
-
|
443
|
-
|
708
|
+
/* Version of OpenSSL that Puma loaded with */
|
709
|
+
rb_define_const(mod, "OPENSSL_LIBRARY_VERSION", rb_str_new2(OpenSSL_version(OPENSSL_VERSION)));
|
710
|
+
#else
|
711
|
+
rb_define_const(mod, "OPENSSL_LIBRARY_VERSION", rb_str_new2(SSLeay_version(SSLEAY_VERSION)));
|
712
|
+
#endif
|
713
|
+
|
714
|
+
#if defined(OPENSSL_NO_SSL3) || defined(OPENSSL_NO_SSL3_METHOD)
|
715
|
+
/* True if SSL3 is not available */
|
716
|
+
rb_define_const(mod, "OPENSSL_NO_SSL3", Qtrue);
|
717
|
+
#else
|
718
|
+
rb_define_const(mod, "OPENSSL_NO_SSL3", Qfalse);
|
719
|
+
#endif
|
720
|
+
|
721
|
+
#if defined(OPENSSL_NO_TLS1) || defined(OPENSSL_NO_TLS1_METHOD)
|
722
|
+
/* True if TLS1 is not available */
|
723
|
+
rb_define_const(mod, "OPENSSL_NO_TLS1", Qtrue);
|
724
|
+
#else
|
725
|
+
rb_define_const(mod, "OPENSSL_NO_TLS1", Qfalse);
|
726
|
+
#endif
|
727
|
+
|
728
|
+
#if defined(OPENSSL_NO_TLS1_1) || defined(OPENSSL_NO_TLS1_1_METHOD)
|
729
|
+
/* True if TLS1_1 is not available */
|
730
|
+
rb_define_const(mod, "OPENSSL_NO_TLS1_1", Qtrue);
|
444
731
|
#else
|
445
|
-
|
732
|
+
rb_define_const(mod, "OPENSSL_NO_TLS1_1", Qfalse);
|
446
733
|
#endif
|
447
734
|
|
448
735
|
rb_define_singleton_method(mod, "check", noop, 0);
|
@@ -463,13 +750,16 @@ void Init_mini_ssl(VALUE puma) {
|
|
463
750
|
rb_define_method(eng, "init?", engine_init, 0);
|
464
751
|
|
465
752
|
rb_define_method(eng, "peercert", engine_peercert, 0);
|
753
|
+
|
754
|
+
rb_define_method(eng, "ssl_vers_st", engine_ssl_vers_st, 0);
|
466
755
|
}
|
467
756
|
|
468
757
|
#else
|
469
758
|
|
759
|
+
NORETURN(VALUE raise_error(VALUE self));
|
760
|
+
|
470
761
|
VALUE raise_error(VALUE self) {
|
471
762
|
rb_raise(rb_eStandardError, "SSL not available in this build");
|
472
|
-
return Qnil;
|
473
763
|
}
|
474
764
|
|
475
765
|
void Init_mini_ssl(VALUE puma) {
|