puma 4.3.12 → 6.3.1
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 +1729 -521
- data/LICENSE +23 -20
- data/README.md +169 -45
- data/bin/puma-wild +3 -9
- data/docs/architecture.md +63 -26
- data/docs/compile_options.md +55 -0
- data/docs/deployment.md +60 -69
- 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/{tools → docs}/jungle/rc.d/puma.conf +0 -0
- data/docs/kubernetes.md +66 -0
- data/docs/nginx.md +2 -2
- data/docs/plugins.md +15 -15
- data/docs/rails_dev_mode.md +28 -0
- data/docs/restart.md +46 -23
- data/docs/signals.md +13 -11
- data/docs/stats.md +142 -0
- data/docs/systemd.md +84 -128
- 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 -4
- data/ext/puma_http11/ext_help.h +1 -1
- data/ext/puma_http11/extconf.rb +49 -12
- data/ext/puma_http11/http11_parser.c +46 -48
- data/ext/puma_http11/http11_parser.h +2 -2
- data/ext/puma_http11/http11_parser.java.rl +3 -3
- data/ext/puma_http11/http11_parser.rl +3 -3
- data/ext/puma_http11/http11_parser_common.rl +2 -2
- data/ext/puma_http11/mini_ssl.c +278 -93
- data/ext/puma_http11/no_ssl/PumaHttp11Service.java +15 -0
- data/ext/puma_http11/org/jruby/puma/Http11.java +6 -6
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +4 -6
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +241 -96
- data/ext/puma_http11/puma_http11.c +46 -57
- data/lib/puma/app/status.rb +53 -39
- data/lib/puma/binder.rb +237 -121
- data/lib/puma/cli.rb +34 -34
- data/lib/puma/client.rb +172 -98
- data/lib/puma/cluster/worker.rb +180 -0
- data/lib/puma/cluster/worker_handle.rb +97 -0
- data/lib/puma/cluster.rb +226 -231
- data/lib/puma/commonlogger.rb +21 -14
- data/lib/puma/configuration.rb +114 -87
- data/lib/puma/const.rb +139 -95
- data/lib/puma/control_cli.rb +99 -79
- data/lib/puma/detect.rb +33 -2
- data/lib/puma/dsl.rb +516 -110
- data/lib/puma/error_logger.rb +113 -0
- data/lib/puma/events.rb +16 -115
- data/lib/puma/io_buffer.rb +44 -2
- 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 +164 -155
- data/lib/puma/log_writer.rb +147 -0
- data/lib/puma/minissl/context_builder.rb +36 -19
- data/lib/puma/minissl.rb +230 -55
- data/lib/puma/null_io.rb +18 -1
- data/lib/puma/plugin/systemd.rb +90 -0
- data/lib/puma/plugin/tmp_restart.rb +1 -1
- data/lib/puma/plugin.rb +3 -12
- data/lib/puma/rack/builder.rb +7 -11
- data/lib/puma/rack/urlmap.rb +0 -0
- data/lib/puma/rack_default.rb +19 -4
- data/lib/puma/reactor.rb +93 -368
- data/lib/puma/request.rb +671 -0
- data/lib/puma/runner.rb +92 -75
- data/lib/puma/sd_notify.rb +149 -0
- data/lib/puma/server.rb +321 -794
- data/lib/puma/single.rb +20 -74
- data/lib/puma/state_file.rb +45 -8
- data/lib/puma/thread_pool.rb +140 -68
- data/lib/puma/util.rb +21 -4
- data/lib/puma.rb +54 -7
- data/lib/rack/handler/puma.rb +113 -87
- data/tools/{docker/Dockerfile → Dockerfile} +1 -1
- data/tools/trickletest.rb +0 -0
- metadata +33 -24
- data/docs/tcp_mode.md +0 -96
- data/ext/puma_http11/io_buffer.c +0 -155
- data/ext/puma_http11/org/jruby/puma/IOBuffer.java +0 -72
- data/lib/puma/accept_nonblock.rb +0 -29
- 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/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,23 +49,13 @@ void engine_free(ms_conn* conn) {
|
|
45
49
|
free(conn);
|
46
50
|
}
|
47
51
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
conn->read = BIO_new(BIO_s_mem());
|
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
|
-
}
|
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
|
+
};
|
64
57
|
|
58
|
+
#ifndef HAVE_SSL_CTX_SET_DH_AUTO
|
65
59
|
DH *get_dh2048(void) {
|
66
60
|
/* `openssl dhparam -C 2048`
|
67
61
|
* -----BEGIN DH PARAMETERS-----
|
@@ -104,13 +98,13 @@ DH *get_dh2048(void) {
|
|
104
98
|
static unsigned char dh2048_g[] = { 0x02 };
|
105
99
|
|
106
100
|
DH *dh;
|
107
|
-
#if !(OPENSSL_VERSION_NUMBER < 0x10100005L
|
101
|
+
#if !(OPENSSL_VERSION_NUMBER < 0x10100005L)
|
108
102
|
BIGNUM *p, *g;
|
109
103
|
#endif
|
110
104
|
|
111
105
|
dh = DH_new();
|
112
106
|
|
113
|
-
#if OPENSSL_VERSION_NUMBER < 0x10100005L
|
107
|
+
#if OPENSSL_VERSION_NUMBER < 0x10100005L
|
114
108
|
dh->p = BN_bin2bn(dh2048_p, sizeof(dh2048_p), NULL);
|
115
109
|
dh->g = BN_bin2bn(dh2048_g, sizeof(dh2048_g), NULL);
|
116
110
|
|
@@ -132,6 +126,38 @@ DH *get_dh2048(void) {
|
|
132
126
|
|
133
127
|
return dh;
|
134
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
|
+
}
|
135
161
|
|
136
162
|
static int engine_verify_callback(int preverify_ok, X509_STORE_CTX* ctx) {
|
137
163
|
X509* err_cert;
|
@@ -159,52 +185,157 @@ static int engine_verify_callback(int preverify_ok, X509_STORE_CTX* ctx) {
|
|
159
185
|
return preverify_ok;
|
160
186
|
}
|
161
187
|
|
162
|
-
|
163
|
-
|
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) {
|
164
224
|
SSL_CTX* ctx;
|
165
|
-
|
166
|
-
|
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;
|
167
244
|
|
168
|
-
|
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
|
169
249
|
|
170
|
-
|
171
|
-
VALUE key = rb_funcall(mini_ssl_ctx, sym_key, 0);
|
250
|
+
key = rb_funcall(mini_ssl_ctx, rb_intern_const("key"), 0);
|
172
251
|
|
173
|
-
|
252
|
+
key_password_command = rb_funcall(mini_ssl_ctx, rb_intern_const("key_password_command"), 0);
|
174
253
|
|
175
|
-
|
176
|
-
VALUE cert = rb_funcall(mini_ssl_ctx, sym_cert, 0);
|
254
|
+
cert = rb_funcall(mini_ssl_ctx, rb_intern_const("cert"), 0);
|
177
255
|
|
178
|
-
|
256
|
+
ca = rb_funcall(mini_ssl_ctx, rb_intern_const("ca"), 0);
|
179
257
|
|
180
|
-
|
181
|
-
VALUE ca = rb_funcall(mini_ssl_ctx, sym_ca, 0);
|
258
|
+
cert_pem = rb_funcall(mini_ssl_ctx, rb_intern_const("cert_pem"), 0);
|
182
259
|
|
183
|
-
|
184
|
-
VALUE verify_mode = rb_funcall(mini_ssl_ctx, sym_verify_mode, 0);
|
260
|
+
key_pem = rb_funcall(mini_ssl_ctx, rb_intern_const("key_pem"), 0);
|
185
261
|
|
186
|
-
|
187
|
-
VALUE ssl_cipher_filter = rb_funcall(mini_ssl_ctx, sym_ssl_cipher_filter, 0);
|
262
|
+
verify_mode = rb_funcall(mini_ssl_ctx, rb_intern_const("verify_mode"), 0);
|
188
263
|
|
189
|
-
|
190
|
-
VALUE no_tlsv1 = rb_funcall(mini_ssl_ctx, sym_no_tlsv1, 0);
|
264
|
+
ssl_cipher_filter = rb_funcall(mini_ssl_ctx, rb_intern_const("ssl_cipher_filter"), 0);
|
191
265
|
|
192
|
-
|
193
|
-
VALUE no_tlsv1_1 = rb_funcall(mini_ssl_ctx, sym_no_tlsv1_1, 0);
|
266
|
+
no_tlsv1 = rb_funcall(mini_ssl_ctx, rb_intern_const("no_tlsv1"), 0);
|
194
267
|
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
ctx = SSL_CTX_new(SSLv23_server_method());
|
199
|
-
#endif
|
200
|
-
conn->ctx = ctx;
|
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);
|
201
271
|
|
202
|
-
|
203
|
-
|
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
|
+
}
|
291
|
+
|
292
|
+
if (!NIL_P(key)) {
|
293
|
+
StringValue(key);
|
294
|
+
|
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
|
+
}
|
299
|
+
|
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);
|
304
|
+
|
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
|
+
}
|
312
|
+
|
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);
|
317
|
+
|
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
|
+
}
|
325
|
+
|
326
|
+
verification_flags = rb_funcall(mini_ssl_ctx, rb_intern_const("verification_flags"), 0);
|
327
|
+
|
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
|
+
}
|
204
333
|
|
205
334
|
if (!NIL_P(ca)) {
|
206
335
|
StringValue(ca);
|
207
|
-
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
|
+
}
|
208
339
|
}
|
209
340
|
|
210
341
|
ssl_options = SSL_OP_CIPHER_SERVER_PREFERENCE | SSL_OP_SINGLE_ECDH_USE | SSL_OP_NO_COMPRESSION;
|
@@ -222,8 +353,6 @@ VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) {
|
|
222
353
|
|
223
354
|
SSL_CTX_set_min_proto_version(ctx, min);
|
224
355
|
|
225
|
-
SSL_CTX_set_options(ctx, ssl_options);
|
226
|
-
|
227
356
|
#else
|
228
357
|
/* As of 1.0.2f, SSL_OP_SINGLE_DH_USE key use is always on */
|
229
358
|
ssl_options |= SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_SINGLE_DH_USE;
|
@@ -234,10 +363,23 @@ VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) {
|
|
234
363
|
if(RTEST(no_tlsv1_1)) {
|
235
364
|
ssl_options |= SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1;
|
236
365
|
}
|
237
|
-
SSL_CTX_set_options(ctx, ssl_options);
|
238
366
|
#endif
|
239
367
|
|
240
|
-
|
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);
|
241
383
|
|
242
384
|
if (!NIL_P(ssl_cipher_filter)) {
|
243
385
|
StringValue(ssl_cipher_filter);
|
@@ -247,6 +389,23 @@ VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) {
|
|
247
389
|
SSL_CTX_set_cipher_list(ctx, "HIGH:!aNULL@STRENGTH");
|
248
390
|
}
|
249
391
|
|
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);
|
395
|
+
if (ecdh) {
|
396
|
+
SSL_CTX_set_tmp_ecdh(ctx, ecdh);
|
397
|
+
EC_KEY_free(ecdh);
|
398
|
+
}
|
399
|
+
#elif OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
|
400
|
+
SSL_CTX_set_ecdh_auto(ctx, 1);
|
401
|
+
#endif
|
402
|
+
|
403
|
+
if (NIL_P(verify_mode)) {
|
404
|
+
/* SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); */
|
405
|
+
} else {
|
406
|
+
SSL_CTX_set_verify(ctx, NUM2INT(verify_mode), engine_verify_callback);
|
407
|
+
}
|
408
|
+
|
250
409
|
// Random.bytes available in Ruby 2.5 and later, Random::DEFAULT deprecated in 3.0
|
251
410
|
session_id_bytes = rb_funcall(
|
252
411
|
#ifdef HAVE_RANDOM_BYTES
|
@@ -261,35 +420,34 @@ VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) {
|
|
261
420
|
(unsigned char *) RSTRING_PTR(session_id_bytes),
|
262
421
|
SSL_MAX_SSL_SESSION_ID_LENGTH);
|
263
422
|
|
264
|
-
|
265
|
-
SSL_CTX_set_tmp_dh(ctx, dh);
|
423
|
+
// printf("\ninitialize end security_level %d\n", SSL_CTX_get_security_level(ctx));
|
266
424
|
|
267
|
-
#
|
268
|
-
//
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
EC_KEY_free(ecdh);
|
274
|
-
}
|
275
|
-
#elif OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
|
276
|
-
// Prior to OpenSSL 1.1.0, servers must manually enable server-side ECDH
|
277
|
-
// negotiation.
|
278
|
-
SSL_CTX_set_ecdh_auto(ctx, 1);
|
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);
|
279
431
|
#endif
|
280
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
|
+
|
281
447
|
ssl = SSL_new(ctx);
|
282
448
|
conn->ssl = ssl;
|
283
449
|
SSL_set_app_data(ssl, NULL);
|
284
|
-
|
285
|
-
if (NIL_P(verify_mode)) {
|
286
|
-
/* SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL); */
|
287
|
-
} else {
|
288
|
-
SSL_set_verify(ssl, NUM2INT(verify_mode), engine_verify_callback);
|
289
|
-
}
|
290
|
-
|
291
450
|
SSL_set_bio(ssl, conn->read, conn->write);
|
292
|
-
|
293
451
|
SSL_set_accept_state(ssl);
|
294
452
|
return obj;
|
295
453
|
}
|
@@ -316,7 +474,7 @@ VALUE engine_inject(VALUE self, VALUE str) {
|
|
316
474
|
ms_conn* conn;
|
317
475
|
long used;
|
318
476
|
|
319
|
-
|
477
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
320
478
|
|
321
479
|
StringValue(str);
|
322
480
|
|
@@ -329,13 +487,14 @@ VALUE engine_inject(VALUE self, VALUE str) {
|
|
329
487
|
return INT2FIX(used);
|
330
488
|
}
|
331
489
|
|
332
|
-
|
490
|
+
NORETURN(void raise_error(SSL* ssl, int result));
|
333
491
|
|
334
492
|
void raise_error(SSL* ssl, int result) {
|
335
493
|
char buf[512];
|
336
494
|
char msg[512];
|
337
495
|
const char* err_str;
|
338
496
|
int err = errno;
|
497
|
+
int mask = 4095;
|
339
498
|
int ssl_err = SSL_get_error(ssl, result);
|
340
499
|
int verify_err = (int) SSL_get_verify_result(ssl);
|
341
500
|
|
@@ -352,8 +511,7 @@ void raise_error(SSL* ssl, int result) {
|
|
352
511
|
} else {
|
353
512
|
err = (int) ERR_get_error();
|
354
513
|
ERR_error_string_n(err, buf, sizeof(buf));
|
355
|
-
snprintf(msg, sizeof(msg), "OpenSSL error: %s - %d", buf, err);
|
356
|
-
|
514
|
+
snprintf(msg, sizeof(msg), "OpenSSL error: %s - %d", buf, err & mask);
|
357
515
|
}
|
358
516
|
} else {
|
359
517
|
snprintf(msg, sizeof(msg), "Unknown OpenSSL error: %d", ssl_err);
|
@@ -368,7 +526,7 @@ VALUE engine_read(VALUE self) {
|
|
368
526
|
char buf[512];
|
369
527
|
int bytes, error;
|
370
528
|
|
371
|
-
|
529
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
372
530
|
|
373
531
|
ERR_clear_error();
|
374
532
|
|
@@ -395,7 +553,7 @@ VALUE engine_write(VALUE self, VALUE str) {
|
|
395
553
|
ms_conn* conn;
|
396
554
|
int bytes;
|
397
555
|
|
398
|
-
|
556
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
399
557
|
|
400
558
|
StringValue(str);
|
401
559
|
|
@@ -417,9 +575,11 @@ VALUE engine_extract(VALUE self) {
|
|
417
575
|
ms_conn* conn;
|
418
576
|
int bytes;
|
419
577
|
size_t pending;
|
420
|
-
|
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];
|
421
581
|
|
422
|
-
|
582
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
423
583
|
|
424
584
|
pending = BIO_pending(conn->write);
|
425
585
|
if(pending > 0) {
|
@@ -438,7 +598,7 @@ VALUE engine_shutdown(VALUE self) {
|
|
438
598
|
ms_conn* conn;
|
439
599
|
int ok;
|
440
600
|
|
441
|
-
|
601
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
442
602
|
|
443
603
|
ERR_clear_error();
|
444
604
|
|
@@ -453,7 +613,7 @@ VALUE engine_shutdown(VALUE self) {
|
|
453
613
|
VALUE engine_init(VALUE self) {
|
454
614
|
ms_conn* conn;
|
455
615
|
|
456
|
-
|
616
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
457
617
|
|
458
618
|
return SSL_in_init(conn->ssl) ? Qtrue : Qfalse;
|
459
619
|
}
|
@@ -466,9 +626,13 @@ VALUE engine_peercert(VALUE self) {
|
|
466
626
|
ms_cert_buf* cert_buf = NULL;
|
467
627
|
VALUE rb_cert_buf;
|
468
628
|
|
469
|
-
|
629
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
470
630
|
|
631
|
+
#ifdef HAVE_SSL_GET1_PEER_CERTIFICATE
|
632
|
+
cert = SSL_get1_peer_certificate(conn->ssl);
|
633
|
+
#else
|
471
634
|
cert = SSL_get_peer_certificate(conn->ssl);
|
635
|
+
#endif
|
472
636
|
if(!cert) {
|
473
637
|
/*
|
474
638
|
* See if there was a failed certificate associated with this client.
|
@@ -497,12 +661,22 @@ VALUE engine_peercert(VALUE self) {
|
|
497
661
|
return rb_cert_buf;
|
498
662
|
}
|
499
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
|
+
|
500
674
|
VALUE noop(VALUE self) {
|
501
675
|
return Qnil;
|
502
676
|
}
|
503
677
|
|
504
678
|
void Init_mini_ssl(VALUE puma) {
|
505
|
-
VALUE mod, eng;
|
679
|
+
VALUE mod, eng, sslctx;
|
506
680
|
|
507
681
|
/* Fake operation for documentation (RDoc, YARD) */
|
508
682
|
#if 0 == 1
|
@@ -515,7 +689,15 @@ void Init_mini_ssl(VALUE puma) {
|
|
515
689
|
ERR_load_crypto_strings();
|
516
690
|
|
517
691
|
mod = rb_define_module_under(puma, "MiniSSL");
|
692
|
+
|
518
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
|
+
|
519
701
|
|
520
702
|
// OpenSSL Build / Runtime/Load versions
|
521
703
|
|
@@ -568,13 +750,16 @@ void Init_mini_ssl(VALUE puma) {
|
|
568
750
|
rb_define_method(eng, "init?", engine_init, 0);
|
569
751
|
|
570
752
|
rb_define_method(eng, "peercert", engine_peercert, 0);
|
753
|
+
|
754
|
+
rb_define_method(eng, "ssl_vers_st", engine_ssl_vers_st, 0);
|
571
755
|
}
|
572
756
|
|
573
757
|
#else
|
574
758
|
|
759
|
+
NORETURN(VALUE raise_error(VALUE self));
|
760
|
+
|
575
761
|
VALUE raise_error(VALUE self) {
|
576
762
|
rb_raise(rb_eStandardError, "SSL not available in this build");
|
577
|
-
return Qnil;
|
578
763
|
}
|
579
764
|
|
580
765
|
void Init_mini_ssl(VALUE puma) {
|
@@ -0,0 +1,15 @@
|
|
1
|
+
package puma;
|
2
|
+
|
3
|
+
import java.io.IOException;
|
4
|
+
|
5
|
+
import org.jruby.Ruby;
|
6
|
+
import org.jruby.runtime.load.BasicLibraryService;
|
7
|
+
|
8
|
+
import org.jruby.puma.Http11;
|
9
|
+
|
10
|
+
public class PumaHttp11Service implements BasicLibraryService {
|
11
|
+
public boolean basicLoad(final Ruby runtime) throws IOException {
|
12
|
+
Http11.createHttp11(runtime);
|
13
|
+
return true;
|
14
|
+
}
|
15
|
+
}
|
@@ -30,8 +30,8 @@ public class Http11 extends RubyObject {
|
|
30
30
|
public final static String MAX_REQUEST_URI_LENGTH_ERR = "HTTP element REQUEST_URI is longer than the 12288 allowed length.";
|
31
31
|
public final static int MAX_FRAGMENT_LENGTH = 1024;
|
32
32
|
public final static String MAX_FRAGMENT_LENGTH_ERR = "HTTP element REQUEST_PATH is longer than the 1024 allowed length.";
|
33
|
-
public final static int MAX_REQUEST_PATH_LENGTH =
|
34
|
-
public final static String MAX_REQUEST_PATH_LENGTH_ERR = "HTTP element REQUEST_PATH is longer than the
|
33
|
+
public final static int MAX_REQUEST_PATH_LENGTH = 8192;
|
34
|
+
public final static String MAX_REQUEST_PATH_LENGTH_ERR = "HTTP element REQUEST_PATH is longer than the 8192 allowed length.";
|
35
35
|
public final static int MAX_QUERY_STRING_LENGTH = 1024 * 10;
|
36
36
|
public final static String MAX_QUERY_STRING_LENGTH_ERR = "HTTP element QUERY_STRING is longer than the 10240 allowed length.";
|
37
37
|
public final static int MAX_HEADER_LENGTH = 1024 * (80 + 32);
|
@@ -46,7 +46,7 @@ public class Http11 extends RubyObject {
|
|
46
46
|
public static final ByteList FRAGMENT_BYTELIST = new ByteList(ByteList.plain("FRAGMENT"));
|
47
47
|
public static final ByteList REQUEST_PATH_BYTELIST = new ByteList(ByteList.plain("REQUEST_PATH"));
|
48
48
|
public static final ByteList QUERY_STRING_BYTELIST = new ByteList(ByteList.plain("QUERY_STRING"));
|
49
|
-
public static final ByteList
|
49
|
+
public static final ByteList SERVER_PROTOCOL_BYTELIST = new ByteList(ByteList.plain("SERVER_PROTOCOL"));
|
50
50
|
|
51
51
|
private static ObjectAllocator ALLOCATOR = new ObjectAllocator() {
|
52
52
|
public IRubyObject allocate(Ruby runtime, RubyClass klass) {
|
@@ -153,9 +153,9 @@ public class Http11 extends RubyObject {
|
|
153
153
|
req.fastASet(RubyString.newStringShared(runtime, QUERY_STRING_BYTELIST),val);
|
154
154
|
}
|
155
155
|
|
156
|
-
public static void
|
156
|
+
public static void server_protocol(Ruby runtime, RubyHash req, ByteList buffer, int at, int length) {
|
157
157
|
RubyString val = RubyString.newString(runtime,new ByteList(buffer,at,length));
|
158
|
-
req.fastASet(RubyString.newStringShared(runtime,
|
158
|
+
req.fastASet(RubyString.newStringShared(runtime, SERVER_PROTOCOL_BYTELIST),val);
|
159
159
|
}
|
160
160
|
|
161
161
|
public void header_done(Ruby runtime, RubyHash req, ByteList buffer, int at, int length) {
|
@@ -197,7 +197,7 @@ public class Http11 extends RubyObject {
|
|
197
197
|
validateMaxLength(runtime, parser.nread,MAX_HEADER_LENGTH, MAX_HEADER_LENGTH_ERR);
|
198
198
|
|
199
199
|
if(hp.has_error()) {
|
200
|
-
throw newHTTPParserError(runtime, "Invalid HTTP format, parsing fails.");
|
200
|
+
throw newHTTPParserError(runtime, "Invalid HTTP format, parsing fails. Are you trying to open an SSL connection to a non-SSL Puma?");
|
201
201
|
} else {
|
202
202
|
return runtime.newFixnum(parser.nread);
|
203
203
|
}
|
@@ -184,8 +184,6 @@ static final int puma_parser_start = 1;
|
|
184
184
|
static final int puma_parser_first_final = 46;
|
185
185
|
static final int puma_parser_error = 0;
|
186
186
|
|
187
|
-
static final int puma_parser_en_main = 1;
|
188
|
-
|
189
187
|
|
190
188
|
// line 62 "ext/puma_http11/http11_parser.java.rl"
|
191
189
|
|
@@ -214,7 +212,7 @@ static final int puma_parser_en_main = 1;
|
|
214
212
|
cs = 0;
|
215
213
|
|
216
214
|
|
217
|
-
// line
|
215
|
+
// line 216 "ext/puma_http11/org/jruby/puma/Http11Parser.java"
|
218
216
|
{
|
219
217
|
cs = puma_parser_start;
|
220
218
|
}
|
@@ -246,7 +244,7 @@ static final int puma_parser_en_main = 1;
|
|
246
244
|
parser.buffer = buffer;
|
247
245
|
|
248
246
|
|
249
|
-
// line
|
247
|
+
// line 248 "ext/puma_http11/org/jruby/puma/Http11Parser.java"
|
250
248
|
{
|
251
249
|
int _klen;
|
252
250
|
int _trans = 0;
|
@@ -385,7 +383,7 @@ case 1:
|
|
385
383
|
case 11:
|
386
384
|
// line 42 "ext/puma_http11/http11_parser.java.rl"
|
387
385
|
{
|
388
|
-
Http11.
|
386
|
+
Http11.server_protocol(runtime, parser.data, parser.buffer, parser.mark, p-parser.mark);
|
389
387
|
}
|
390
388
|
break;
|
391
389
|
case 12:
|
@@ -402,7 +400,7 @@ case 1:
|
|
402
400
|
{ p += 1; _goto_targ = 5; if (true) continue _goto;}
|
403
401
|
}
|
404
402
|
break;
|
405
|
-
// line
|
403
|
+
// line 404 "ext/puma_http11/org/jruby/puma/Http11Parser.java"
|
406
404
|
}
|
407
405
|
}
|
408
406
|
}
|