puma 4.3.12 → 6.0.2
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 +1618 -521
- data/LICENSE +23 -20
- data/README.md +130 -42
- 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/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 +85 -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 +250 -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 +52 -38
- data/lib/puma/binder.rb +232 -119
- data/lib/puma/cli.rb +33 -33
- data/lib/puma/client.rb +129 -88
- data/lib/puma/cluster/worker.rb +175 -0
- data/lib/puma/cluster/worker_handle.rb +97 -0
- data/lib/puma/cluster.rb +224 -231
- data/lib/puma/commonlogger.rb +2 -2
- data/lib/puma/configuration.rb +112 -87
- data/lib/puma/const.rb +86 -91
- data/lib/puma/control_cli.rb +99 -79
- data/lib/puma/detect.rb +31 -2
- data/lib/puma/dsl.rb +426 -110
- data/lib/puma/error_logger.rb +112 -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 +170 -148
- data/lib/puma/log_writer.rb +137 -0
- data/lib/puma/minissl/context_builder.rb +35 -19
- data/lib/puma/minissl.rb +213 -55
- data/lib/puma/null_io.rb +18 -1
- data/lib/puma/plugin/tmp_restart.rb +1 -1
- data/lib/puma/plugin.rb +3 -12
- data/lib/puma/rack/builder.rb +5 -9
- data/lib/puma/rack_default.rb +1 -1
- data/lib/puma/reactor.rb +85 -369
- data/lib/puma/request.rb +644 -0
- data/lib/puma/runner.rb +86 -76
- data/lib/puma/server.rb +306 -793
- data/lib/puma/single.rb +18 -74
- data/lib/puma/state_file.rb +45 -8
- data/lib/puma/systemd.rb +47 -0
- data/lib/puma/thread_pool.rb +136 -68
- data/lib/puma/util.rb +21 -4
- data/lib/puma.rb +54 -7
- data/lib/rack/handler/puma.rb +11 -12
- data/tools/{docker/Dockerfile → Dockerfile} +1 -1
- metadata +31 -23
- 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,129 @@ 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 VALUE
|
189
|
+
sslctx_alloc(VALUE klass) {
|
190
|
+
SSL_CTX *ctx;
|
191
|
+
long mode = 0 |
|
192
|
+
SSL_MODE_ENABLE_PARTIAL_WRITE |
|
193
|
+
SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
|
194
|
+
SSL_MODE_RELEASE_BUFFERS;
|
195
|
+
|
196
|
+
#ifdef HAVE_TLS_SERVER_METHOD
|
197
|
+
ctx = SSL_CTX_new(TLS_method());
|
198
|
+
// printf("\nctx using TLS_method security_level %d\n", SSL_CTX_get_security_level(ctx));
|
199
|
+
#else
|
200
|
+
ctx = SSL_CTX_new(SSLv23_method());
|
201
|
+
#endif
|
202
|
+
if (!ctx) {
|
203
|
+
rb_raise(eError, "SSL_CTX_new");
|
204
|
+
}
|
205
|
+
SSL_CTX_set_mode(ctx, mode);
|
206
|
+
|
207
|
+
return TypedData_Wrap_Struct(klass, &sslctx_type, ctx);
|
208
|
+
}
|
209
|
+
|
210
|
+
VALUE
|
211
|
+
sslctx_initialize(VALUE self, VALUE mini_ssl_ctx) {
|
164
212
|
SSL_CTX* ctx;
|
165
|
-
|
166
|
-
|
213
|
+
int ssl_options;
|
214
|
+
VALUE key, cert, ca, verify_mode, ssl_cipher_filter, no_tlsv1, no_tlsv1_1,
|
215
|
+
verification_flags, session_id_bytes, cert_pem, key_pem;
|
216
|
+
BIO *bio;
|
217
|
+
X509 *x509;
|
218
|
+
EVP_PKEY *pkey;
|
219
|
+
#ifdef HAVE_SSL_CTX_SET_MIN_PROTO_VERSION
|
220
|
+
int min;
|
221
|
+
#endif
|
222
|
+
#ifndef HAVE_SSL_CTX_SET_DH_AUTO
|
223
|
+
DH *dh;
|
224
|
+
#endif
|
225
|
+
#if OPENSSL_VERSION_NUMBER < 0x10002000L
|
226
|
+
EC_KEY *ecdh;
|
227
|
+
#endif
|
228
|
+
#ifdef HAVE_SSL_CTX_SET_SESSION_CACHE_MODE
|
229
|
+
VALUE reuse, reuse_cache_size, reuse_timeout;
|
167
230
|
|
168
|
-
|
231
|
+
reuse = rb_funcall(mini_ssl_ctx, rb_intern_const("reuse"), 0);
|
232
|
+
reuse_cache_size = rb_funcall(mini_ssl_ctx, rb_intern_const("reuse_cache_size"), 0);
|
233
|
+
reuse_timeout = rb_funcall(mini_ssl_ctx, rb_intern_const("reuse_timeout"), 0);
|
234
|
+
#endif
|
169
235
|
|
170
|
-
|
171
|
-
VALUE key = rb_funcall(mini_ssl_ctx, sym_key, 0);
|
236
|
+
key = rb_funcall(mini_ssl_ctx, rb_intern_const("key"), 0);
|
172
237
|
|
173
|
-
|
238
|
+
cert = rb_funcall(mini_ssl_ctx, rb_intern_const("cert"), 0);
|
174
239
|
|
175
|
-
|
176
|
-
VALUE cert = rb_funcall(mini_ssl_ctx, sym_cert, 0);
|
240
|
+
ca = rb_funcall(mini_ssl_ctx, rb_intern_const("ca"), 0);
|
177
241
|
|
178
|
-
|
242
|
+
cert_pem = rb_funcall(mini_ssl_ctx, rb_intern_const("cert_pem"), 0);
|
179
243
|
|
180
|
-
|
181
|
-
VALUE ca = rb_funcall(mini_ssl_ctx, sym_ca, 0);
|
244
|
+
key_pem = rb_funcall(mini_ssl_ctx, rb_intern_const("key_pem"), 0);
|
182
245
|
|
183
|
-
|
184
|
-
VALUE verify_mode = rb_funcall(mini_ssl_ctx, sym_verify_mode, 0);
|
246
|
+
verify_mode = rb_funcall(mini_ssl_ctx, rb_intern_const("verify_mode"), 0);
|
185
247
|
|
186
|
-
|
187
|
-
VALUE ssl_cipher_filter = rb_funcall(mini_ssl_ctx, sym_ssl_cipher_filter, 0);
|
248
|
+
ssl_cipher_filter = rb_funcall(mini_ssl_ctx, rb_intern_const("ssl_cipher_filter"), 0);
|
188
249
|
|
189
|
-
|
190
|
-
VALUE no_tlsv1 = rb_funcall(mini_ssl_ctx, sym_no_tlsv1, 0);
|
250
|
+
no_tlsv1 = rb_funcall(mini_ssl_ctx, rb_intern_const("no_tlsv1"), 0);
|
191
251
|
|
192
|
-
|
193
|
-
VALUE no_tlsv1_1 = rb_funcall(mini_ssl_ctx, sym_no_tlsv1_1, 0);
|
252
|
+
no_tlsv1_1 = rb_funcall(mini_ssl_ctx, rb_intern_const("no_tlsv1_1"), 0);
|
194
253
|
|
195
|
-
|
196
|
-
ctx = SSL_CTX_new(TLS_server_method());
|
197
|
-
#else
|
198
|
-
ctx = SSL_CTX_new(SSLv23_server_method());
|
199
|
-
#endif
|
200
|
-
conn->ctx = ctx;
|
254
|
+
TypedData_Get_Struct(self, SSL_CTX, &sslctx_type, ctx);
|
201
255
|
|
202
|
-
|
203
|
-
|
256
|
+
if (!NIL_P(cert)) {
|
257
|
+
StringValue(cert);
|
258
|
+
|
259
|
+
if (SSL_CTX_use_certificate_chain_file(ctx, RSTRING_PTR(cert)) != 1) {
|
260
|
+
raise_file_error("SSL_CTX_use_certificate_chain_file", RSTRING_PTR(cert));
|
261
|
+
}
|
262
|
+
}
|
263
|
+
|
264
|
+
if (!NIL_P(key)) {
|
265
|
+
StringValue(key);
|
266
|
+
|
267
|
+
if (SSL_CTX_use_PrivateKey_file(ctx, RSTRING_PTR(key), SSL_FILETYPE_PEM) != 1) {
|
268
|
+
raise_file_error("SSL_CTX_use_PrivateKey_file", RSTRING_PTR(key));
|
269
|
+
}
|
270
|
+
}
|
271
|
+
|
272
|
+
if (!NIL_P(cert_pem)) {
|
273
|
+
bio = BIO_new(BIO_s_mem());
|
274
|
+
BIO_puts(bio, RSTRING_PTR(cert_pem));
|
275
|
+
x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
|
276
|
+
|
277
|
+
if (SSL_CTX_use_certificate(ctx, x509) != 1) {
|
278
|
+
BIO_free(bio);
|
279
|
+
raise_file_error("SSL_CTX_use_certificate", RSTRING_PTR(cert_pem));
|
280
|
+
}
|
281
|
+
X509_free(x509);
|
282
|
+
BIO_free(bio);
|
283
|
+
}
|
284
|
+
|
285
|
+
if (!NIL_P(key_pem)) {
|
286
|
+
bio = BIO_new(BIO_s_mem());
|
287
|
+
BIO_puts(bio, RSTRING_PTR(key_pem));
|
288
|
+
pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
|
289
|
+
|
290
|
+
if (SSL_CTX_use_PrivateKey(ctx, pkey) != 1) {
|
291
|
+
BIO_free(bio);
|
292
|
+
raise_file_error("SSL_CTX_use_PrivateKey", RSTRING_PTR(key_pem));
|
293
|
+
}
|
294
|
+
EVP_PKEY_free(pkey);
|
295
|
+
BIO_free(bio);
|
296
|
+
}
|
297
|
+
|
298
|
+
verification_flags = rb_funcall(mini_ssl_ctx, rb_intern_const("verification_flags"), 0);
|
299
|
+
|
300
|
+
if (!NIL_P(verification_flags)) {
|
301
|
+
X509_VERIFY_PARAM *param = SSL_CTX_get0_param(ctx);
|
302
|
+
X509_VERIFY_PARAM_set_flags(param, NUM2INT(verification_flags));
|
303
|
+
SSL_CTX_set1_param(ctx, param);
|
304
|
+
}
|
204
305
|
|
205
306
|
if (!NIL_P(ca)) {
|
206
307
|
StringValue(ca);
|
207
|
-
SSL_CTX_load_verify_locations(ctx, RSTRING_PTR(ca), NULL)
|
308
|
+
if (SSL_CTX_load_verify_locations(ctx, RSTRING_PTR(ca), NULL) != 1) {
|
309
|
+
raise_file_error("SSL_CTX_load_verify_locations", RSTRING_PTR(ca));
|
310
|
+
}
|
208
311
|
}
|
209
312
|
|
210
313
|
ssl_options = SSL_OP_CIPHER_SERVER_PREFERENCE | SSL_OP_SINGLE_ECDH_USE | SSL_OP_NO_COMPRESSION;
|
@@ -222,8 +325,6 @@ VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) {
|
|
222
325
|
|
223
326
|
SSL_CTX_set_min_proto_version(ctx, min);
|
224
327
|
|
225
|
-
SSL_CTX_set_options(ctx, ssl_options);
|
226
|
-
|
227
328
|
#else
|
228
329
|
/* As of 1.0.2f, SSL_OP_SINGLE_DH_USE key use is always on */
|
229
330
|
ssl_options |= SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_SINGLE_DH_USE;
|
@@ -234,10 +335,23 @@ VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) {
|
|
234
335
|
if(RTEST(no_tlsv1_1)) {
|
235
336
|
ssl_options |= SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1;
|
236
337
|
}
|
237
|
-
SSL_CTX_set_options(ctx, ssl_options);
|
238
338
|
#endif
|
239
339
|
|
240
|
-
|
340
|
+
#ifdef HAVE_SSL_CTX_SET_SESSION_CACHE_MODE
|
341
|
+
if (!NIL_P(reuse)) {
|
342
|
+
SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER);
|
343
|
+
if (!NIL_P(reuse_cache_size)) {
|
344
|
+
SSL_CTX_sess_set_cache_size(ctx, NUM2INT(reuse_cache_size));
|
345
|
+
}
|
346
|
+
if (!NIL_P(reuse_timeout)) {
|
347
|
+
SSL_CTX_set_timeout(ctx, NUM2INT(reuse_timeout));
|
348
|
+
}
|
349
|
+
} else {
|
350
|
+
SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
|
351
|
+
}
|
352
|
+
#endif
|
353
|
+
|
354
|
+
SSL_CTX_set_options(ctx, ssl_options);
|
241
355
|
|
242
356
|
if (!NIL_P(ssl_cipher_filter)) {
|
243
357
|
StringValue(ssl_cipher_filter);
|
@@ -247,6 +361,23 @@ VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) {
|
|
247
361
|
SSL_CTX_set_cipher_list(ctx, "HIGH:!aNULL@STRENGTH");
|
248
362
|
}
|
249
363
|
|
364
|
+
#if OPENSSL_VERSION_NUMBER < 0x10002000L
|
365
|
+
// Remove this case if OpenSSL 1.0.1 (now EOL) support is no longer needed.
|
366
|
+
ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
|
367
|
+
if (ecdh) {
|
368
|
+
SSL_CTX_set_tmp_ecdh(ctx, ecdh);
|
369
|
+
EC_KEY_free(ecdh);
|
370
|
+
}
|
371
|
+
#elif OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
|
372
|
+
SSL_CTX_set_ecdh_auto(ctx, 1);
|
373
|
+
#endif
|
374
|
+
|
375
|
+
if (NIL_P(verify_mode)) {
|
376
|
+
/* SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); */
|
377
|
+
} else {
|
378
|
+
SSL_CTX_set_verify(ctx, NUM2INT(verify_mode), engine_verify_callback);
|
379
|
+
}
|
380
|
+
|
250
381
|
// Random.bytes available in Ruby 2.5 and later, Random::DEFAULT deprecated in 3.0
|
251
382
|
session_id_bytes = rb_funcall(
|
252
383
|
#ifdef HAVE_RANDOM_BYTES
|
@@ -261,35 +392,34 @@ VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) {
|
|
261
392
|
(unsigned char *) RSTRING_PTR(session_id_bytes),
|
262
393
|
SSL_MAX_SSL_SESSION_ID_LENGTH);
|
263
394
|
|
264
|
-
|
265
|
-
SSL_CTX_set_tmp_dh(ctx, dh);
|
395
|
+
// printf("\ninitialize end security_level %d\n", SSL_CTX_get_security_level(ctx));
|
266
396
|
|
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);
|
397
|
+
#ifdef HAVE_SSL_CTX_SET_DH_AUTO
|
398
|
+
// https://www.openssl.org/docs/man3.0/man3/SSL_CTX_set_dh_auto.html
|
399
|
+
SSL_CTX_set_dh_auto(ctx, 1);
|
400
|
+
#else
|
401
|
+
dh = get_dh2048();
|
402
|
+
SSL_CTX_set_tmp_dh(ctx, dh);
|
279
403
|
#endif
|
280
404
|
|
405
|
+
rb_obj_freeze(self);
|
406
|
+
return self;
|
407
|
+
}
|
408
|
+
|
409
|
+
VALUE engine_init_server(VALUE self, VALUE sslctx) {
|
410
|
+
ms_conn* conn;
|
411
|
+
VALUE obj;
|
412
|
+
SSL_CTX* ctx;
|
413
|
+
SSL* ssl;
|
414
|
+
|
415
|
+
conn = engine_alloc(self, &obj);
|
416
|
+
|
417
|
+
TypedData_Get_Struct(sslctx, SSL_CTX, &sslctx_type, ctx);
|
418
|
+
|
281
419
|
ssl = SSL_new(ctx);
|
282
420
|
conn->ssl = ssl;
|
283
421
|
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
422
|
SSL_set_bio(ssl, conn->read, conn->write);
|
292
|
-
|
293
423
|
SSL_set_accept_state(ssl);
|
294
424
|
return obj;
|
295
425
|
}
|
@@ -316,7 +446,7 @@ VALUE engine_inject(VALUE self, VALUE str) {
|
|
316
446
|
ms_conn* conn;
|
317
447
|
long used;
|
318
448
|
|
319
|
-
|
449
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
320
450
|
|
321
451
|
StringValue(str);
|
322
452
|
|
@@ -329,13 +459,14 @@ VALUE engine_inject(VALUE self, VALUE str) {
|
|
329
459
|
return INT2FIX(used);
|
330
460
|
}
|
331
461
|
|
332
|
-
|
462
|
+
NORETURN(void raise_error(SSL* ssl, int result));
|
333
463
|
|
334
464
|
void raise_error(SSL* ssl, int result) {
|
335
465
|
char buf[512];
|
336
466
|
char msg[512];
|
337
467
|
const char* err_str;
|
338
468
|
int err = errno;
|
469
|
+
int mask = 4095;
|
339
470
|
int ssl_err = SSL_get_error(ssl, result);
|
340
471
|
int verify_err = (int) SSL_get_verify_result(ssl);
|
341
472
|
|
@@ -352,8 +483,7 @@ void raise_error(SSL* ssl, int result) {
|
|
352
483
|
} else {
|
353
484
|
err = (int) ERR_get_error();
|
354
485
|
ERR_error_string_n(err, buf, sizeof(buf));
|
355
|
-
snprintf(msg, sizeof(msg), "OpenSSL error: %s - %d", buf, err);
|
356
|
-
|
486
|
+
snprintf(msg, sizeof(msg), "OpenSSL error: %s - %d", buf, err & mask);
|
357
487
|
}
|
358
488
|
} else {
|
359
489
|
snprintf(msg, sizeof(msg), "Unknown OpenSSL error: %d", ssl_err);
|
@@ -368,7 +498,7 @@ VALUE engine_read(VALUE self) {
|
|
368
498
|
char buf[512];
|
369
499
|
int bytes, error;
|
370
500
|
|
371
|
-
|
501
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
372
502
|
|
373
503
|
ERR_clear_error();
|
374
504
|
|
@@ -395,7 +525,7 @@ VALUE engine_write(VALUE self, VALUE str) {
|
|
395
525
|
ms_conn* conn;
|
396
526
|
int bytes;
|
397
527
|
|
398
|
-
|
528
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
399
529
|
|
400
530
|
StringValue(str);
|
401
531
|
|
@@ -417,9 +547,11 @@ VALUE engine_extract(VALUE self) {
|
|
417
547
|
ms_conn* conn;
|
418
548
|
int bytes;
|
419
549
|
size_t pending;
|
420
|
-
|
550
|
+
// https://www.openssl.org/docs/manmaster/man3/BIO_f_buffer.html
|
551
|
+
// crypto/bio/bf_buff.c DEFAULT_BUFFER_SIZE
|
552
|
+
char buf[4096];
|
421
553
|
|
422
|
-
|
554
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
423
555
|
|
424
556
|
pending = BIO_pending(conn->write);
|
425
557
|
if(pending > 0) {
|
@@ -438,7 +570,7 @@ VALUE engine_shutdown(VALUE self) {
|
|
438
570
|
ms_conn* conn;
|
439
571
|
int ok;
|
440
572
|
|
441
|
-
|
573
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
442
574
|
|
443
575
|
ERR_clear_error();
|
444
576
|
|
@@ -453,7 +585,7 @@ VALUE engine_shutdown(VALUE self) {
|
|
453
585
|
VALUE engine_init(VALUE self) {
|
454
586
|
ms_conn* conn;
|
455
587
|
|
456
|
-
|
588
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
457
589
|
|
458
590
|
return SSL_in_init(conn->ssl) ? Qtrue : Qfalse;
|
459
591
|
}
|
@@ -466,9 +598,13 @@ VALUE engine_peercert(VALUE self) {
|
|
466
598
|
ms_cert_buf* cert_buf = NULL;
|
467
599
|
VALUE rb_cert_buf;
|
468
600
|
|
469
|
-
|
601
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
470
602
|
|
603
|
+
#ifdef HAVE_SSL_GET1_PEER_CERTIFICATE
|
604
|
+
cert = SSL_get1_peer_certificate(conn->ssl);
|
605
|
+
#else
|
471
606
|
cert = SSL_get_peer_certificate(conn->ssl);
|
607
|
+
#endif
|
472
608
|
if(!cert) {
|
473
609
|
/*
|
474
610
|
* See if there was a failed certificate associated with this client.
|
@@ -497,12 +633,22 @@ VALUE engine_peercert(VALUE self) {
|
|
497
633
|
return rb_cert_buf;
|
498
634
|
}
|
499
635
|
|
636
|
+
/* @see Puma::MiniSSL::Socket#ssl_version_state
|
637
|
+
* @version 5.0.0
|
638
|
+
*/
|
639
|
+
static VALUE
|
640
|
+
engine_ssl_vers_st(VALUE self) {
|
641
|
+
ms_conn* conn;
|
642
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
643
|
+
return rb_ary_new3(2, rb_str_new2(SSL_get_version(conn->ssl)), rb_str_new2(SSL_state_string(conn->ssl)));
|
644
|
+
}
|
645
|
+
|
500
646
|
VALUE noop(VALUE self) {
|
501
647
|
return Qnil;
|
502
648
|
}
|
503
649
|
|
504
650
|
void Init_mini_ssl(VALUE puma) {
|
505
|
-
VALUE mod, eng;
|
651
|
+
VALUE mod, eng, sslctx;
|
506
652
|
|
507
653
|
/* Fake operation for documentation (RDoc, YARD) */
|
508
654
|
#if 0 == 1
|
@@ -515,7 +661,15 @@ void Init_mini_ssl(VALUE puma) {
|
|
515
661
|
ERR_load_crypto_strings();
|
516
662
|
|
517
663
|
mod = rb_define_module_under(puma, "MiniSSL");
|
664
|
+
|
518
665
|
eng = rb_define_class_under(mod, "Engine", rb_cObject);
|
666
|
+
rb_undef_alloc_func(eng);
|
667
|
+
|
668
|
+
sslctx = rb_define_class_under(mod, "SSLContext", rb_cObject);
|
669
|
+
rb_define_alloc_func(sslctx, sslctx_alloc);
|
670
|
+
rb_define_method(sslctx, "initialize", sslctx_initialize, 1);
|
671
|
+
rb_undef_method(sslctx, "initialize_copy");
|
672
|
+
|
519
673
|
|
520
674
|
// OpenSSL Build / Runtime/Load versions
|
521
675
|
|
@@ -568,13 +722,16 @@ void Init_mini_ssl(VALUE puma) {
|
|
568
722
|
rb_define_method(eng, "init?", engine_init, 0);
|
569
723
|
|
570
724
|
rb_define_method(eng, "peercert", engine_peercert, 0);
|
725
|
+
|
726
|
+
rb_define_method(eng, "ssl_vers_st", engine_ssl_vers_st, 0);
|
571
727
|
}
|
572
728
|
|
573
729
|
#else
|
574
730
|
|
731
|
+
NORETURN(VALUE raise_error(VALUE self));
|
732
|
+
|
575
733
|
VALUE raise_error(VALUE self) {
|
576
734
|
rb_raise(rb_eStandardError, "SSL not available in this build");
|
577
|
-
return Qnil;
|
578
735
|
}
|
579
736
|
|
580
737
|
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
|
}
|