puma 4.3.8 → 5.6.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/History.md +1543 -521
- data/LICENSE +23 -20
- data/README.md +120 -36
- data/bin/puma-wild +3 -9
- data/docs/architecture.md +63 -26
- data/docs/compile_options.md +21 -0
- data/docs/deployment.md +60 -69
- data/docs/fork_worker.md +33 -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 +1 -1
- 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/ext/puma_http11/PumaHttp11Service.java +2 -4
- data/ext/puma_http11/ext_help.h +1 -1
- data/ext/puma_http11/extconf.rb +51 -9
- data/ext/puma_http11/http11_parser.c +68 -57
- data/ext/puma_http11/http11_parser.h +1 -1
- data/ext/puma_http11/http11_parser.java.rl +1 -1
- data/ext/puma_http11/http11_parser.rl +1 -1
- data/ext/puma_http11/http11_parser_common.rl +1 -1
- data/ext/puma_http11/mini_ssl.c +295 -124
- data/ext/puma_http11/no_ssl/PumaHttp11Service.java +15 -0
- data/ext/puma_http11/org/jruby/puma/Http11.java +5 -3
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +51 -51
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +109 -67
- data/ext/puma_http11/puma_http11.c +32 -51
- data/lib/puma/app/status.rb +50 -36
- data/lib/puma/binder.rb +225 -106
- data/lib/puma/cli.rb +24 -18
- data/lib/puma/client.rb +197 -92
- data/lib/puma/cluster/worker.rb +173 -0
- data/lib/puma/cluster/worker_handle.rb +94 -0
- data/lib/puma/cluster.rb +212 -220
- data/lib/puma/commonlogger.rb +2 -2
- data/lib/puma/configuration.rb +58 -49
- data/lib/puma/const.rb +26 -9
- data/lib/puma/control_cli.rb +99 -76
- data/lib/puma/detect.rb +29 -2
- data/lib/puma/dsl.rb +368 -96
- data/lib/puma/error_logger.rb +104 -0
- data/lib/puma/events.rb +55 -34
- data/lib/puma/io_buffer.rb +9 -2
- data/lib/puma/jruby_restart.rb +0 -58
- data/lib/puma/json_serialization.rb +96 -0
- data/lib/puma/launcher.rb +128 -46
- data/lib/puma/minissl/context_builder.rb +14 -9
- data/lib/puma/minissl.rb +137 -50
- data/lib/puma/null_io.rb +18 -1
- data/lib/puma/plugin.rb +3 -12
- data/lib/puma/queue_close.rb +26 -0
- data/lib/puma/rack/builder.rb +1 -5
- data/lib/puma/reactor.rb +85 -369
- data/lib/puma/request.rb +489 -0
- data/lib/puma/runner.rb +46 -61
- data/lib/puma/server.rb +292 -751
- data/lib/puma/single.rb +9 -65
- data/lib/puma/state_file.rb +48 -8
- data/lib/puma/systemd.rb +46 -0
- data/lib/puma/thread_pool.rb +125 -57
- data/lib/puma/util.rb +32 -4
- data/lib/puma.rb +48 -0
- data/lib/rack/handler/puma.rb +2 -3
- data/lib/rack/version_restriction.rb +15 -0
- data/tools/{docker/Dockerfile → Dockerfile} +1 -1
- metadata +29 -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/{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
|
-
|
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
|
|
65
|
-
|
66
|
-
|
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,52 +185,118 @@ 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 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) {
|
143
212
|
SSL_CTX* ctx;
|
144
|
-
SSL* ssl;
|
145
|
-
int min, ssl_options;
|
146
213
|
|
147
|
-
|
214
|
+
#ifdef HAVE_SSL_CTX_SET_MIN_PROTO_VERSION
|
215
|
+
int min;
|
216
|
+
#endif
|
217
|
+
int ssl_options;
|
218
|
+
VALUE key, cert, ca, verify_mode, ssl_cipher_filter, no_tlsv1, no_tlsv1_1,
|
219
|
+
verification_flags, session_id_bytes, cert_pem, key_pem;
|
220
|
+
#ifndef HAVE_SSL_CTX_SET_DH_AUTO
|
221
|
+
DH *dh;
|
222
|
+
#endif
|
223
|
+
BIO *bio;
|
224
|
+
X509 *x509;
|
225
|
+
EVP_PKEY *pkey;
|
148
226
|
|
149
|
-
|
150
|
-
|
227
|
+
#if OPENSSL_VERSION_NUMBER < 0x10002000L
|
228
|
+
EC_KEY *ecdh;
|
229
|
+
#endif
|
151
230
|
|
152
|
-
|
231
|
+
TypedData_Get_Struct(self, SSL_CTX, &sslctx_type, ctx);
|
153
232
|
|
154
|
-
|
155
|
-
VALUE cert = rb_funcall(mini_ssl_ctx, sym_cert, 0);
|
233
|
+
key = rb_funcall(mini_ssl_ctx, rb_intern_const("key"), 0);
|
156
234
|
|
157
|
-
|
235
|
+
cert = rb_funcall(mini_ssl_ctx, rb_intern_const("cert"), 0);
|
158
236
|
|
159
|
-
|
160
|
-
VALUE ca = rb_funcall(mini_ssl_ctx, sym_ca, 0);
|
237
|
+
ca = rb_funcall(mini_ssl_ctx, rb_intern_const("ca"), 0);
|
161
238
|
|
162
|
-
|
163
|
-
VALUE verify_mode = rb_funcall(mini_ssl_ctx, sym_verify_mode, 0);
|
239
|
+
cert_pem = rb_funcall(mini_ssl_ctx, rb_intern_const("cert_pem"), 0);
|
164
240
|
|
165
|
-
|
166
|
-
VALUE ssl_cipher_filter = rb_funcall(mini_ssl_ctx, sym_ssl_cipher_filter, 0);
|
241
|
+
key_pem = rb_funcall(mini_ssl_ctx, rb_intern_const("key_pem"), 0);
|
167
242
|
|
168
|
-
|
169
|
-
VALUE no_tlsv1 = rb_funcall(mini_ssl_ctx, sym_no_tlsv1, 0);
|
243
|
+
verify_mode = rb_funcall(mini_ssl_ctx, rb_intern_const("verify_mode"), 0);
|
170
244
|
|
171
|
-
|
172
|
-
VALUE no_tlsv1_1 = rb_funcall(mini_ssl_ctx, sym_no_tlsv1_1, 0);
|
245
|
+
ssl_cipher_filter = rb_funcall(mini_ssl_ctx, rb_intern_const("ssl_cipher_filter"), 0);
|
173
246
|
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
247
|
+
no_tlsv1 = rb_funcall(mini_ssl_ctx, rb_intern_const("no_tlsv1"), 0);
|
248
|
+
|
249
|
+
no_tlsv1_1 = rb_funcall(mini_ssl_ctx, rb_intern_const("no_tlsv1_1"), 0);
|
250
|
+
|
251
|
+
if (!NIL_P(cert)) {
|
252
|
+
StringValue(cert);
|
253
|
+
|
254
|
+
if (SSL_CTX_use_certificate_chain_file(ctx, RSTRING_PTR(cert)) != 1) {
|
255
|
+
raise_file_error("SSL_CTX_use_certificate_chain_file", RSTRING_PTR(cert));
|
256
|
+
}
|
257
|
+
}
|
258
|
+
|
259
|
+
if (!NIL_P(key)) {
|
260
|
+
StringValue(key);
|
180
261
|
|
181
|
-
|
182
|
-
|
262
|
+
if (SSL_CTX_use_PrivateKey_file(ctx, RSTRING_PTR(key), SSL_FILETYPE_PEM) != 1) {
|
263
|
+
raise_file_error("SSL_CTX_use_PrivateKey_file", RSTRING_PTR(key));
|
264
|
+
}
|
265
|
+
}
|
266
|
+
|
267
|
+
if (!NIL_P(cert_pem)) {
|
268
|
+
bio = BIO_new(BIO_s_mem());
|
269
|
+
BIO_puts(bio, RSTRING_PTR(cert_pem));
|
270
|
+
x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
|
271
|
+
|
272
|
+
if (SSL_CTX_use_certificate(ctx, x509) != 1) {
|
273
|
+
raise_file_error("SSL_CTX_use_certificate", RSTRING_PTR(cert_pem));
|
274
|
+
}
|
275
|
+
}
|
276
|
+
|
277
|
+
if (!NIL_P(key_pem)) {
|
278
|
+
bio = BIO_new(BIO_s_mem());
|
279
|
+
BIO_puts(bio, RSTRING_PTR(key_pem));
|
280
|
+
pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
|
281
|
+
|
282
|
+
if (SSL_CTX_use_PrivateKey(ctx, pkey) != 1) {
|
283
|
+
raise_file_error("SSL_CTX_use_PrivateKey", RSTRING_PTR(key_pem));
|
284
|
+
}
|
285
|
+
}
|
286
|
+
|
287
|
+
verification_flags = rb_funcall(mini_ssl_ctx, rb_intern_const("verification_flags"), 0);
|
288
|
+
|
289
|
+
if (!NIL_P(verification_flags)) {
|
290
|
+
X509_VERIFY_PARAM *param = SSL_CTX_get0_param(ctx);
|
291
|
+
X509_VERIFY_PARAM_set_flags(param, NUM2INT(verification_flags));
|
292
|
+
SSL_CTX_set1_param(ctx, param);
|
293
|
+
}
|
183
294
|
|
184
295
|
if (!NIL_P(ca)) {
|
185
296
|
StringValue(ca);
|
186
|
-
SSL_CTX_load_verify_locations(ctx, RSTRING_PTR(ca), NULL)
|
297
|
+
if (SSL_CTX_load_verify_locations(ctx, RSTRING_PTR(ca), NULL) != 1) {
|
298
|
+
raise_file_error("SSL_CTX_load_verify_locations", RSTRING_PTR(ca));
|
299
|
+
}
|
187
300
|
}
|
188
301
|
|
189
302
|
ssl_options = SSL_OP_CIPHER_SERVER_PREFERENCE | SSL_OP_SINGLE_ECDH_USE | SSL_OP_NO_COMPRESSION;
|
@@ -198,7 +311,7 @@ VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) {
|
|
198
311
|
else {
|
199
312
|
min = TLS1_VERSION;
|
200
313
|
}
|
201
|
-
|
314
|
+
|
202
315
|
SSL_CTX_set_min_proto_version(ctx, min);
|
203
316
|
|
204
317
|
SSL_CTX_set_options(ctx, ssl_options);
|
@@ -226,35 +339,66 @@ VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) {
|
|
226
339
|
SSL_CTX_set_cipher_list(ctx, "HIGH:!aNULL@STRENGTH");
|
227
340
|
}
|
228
341
|
|
229
|
-
DH *dh = get_dh1024();
|
230
|
-
SSL_CTX_set_tmp_dh(ctx, dh);
|
231
|
-
|
232
342
|
#if OPENSSL_VERSION_NUMBER < 0x10002000L
|
233
343
|
// Remove this case if OpenSSL 1.0.1 (now EOL) support is no
|
234
344
|
// longer needed.
|
235
|
-
|
345
|
+
ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
|
236
346
|
if (ecdh) {
|
237
347
|
SSL_CTX_set_tmp_ecdh(ctx, ecdh);
|
238
348
|
EC_KEY_free(ecdh);
|
239
349
|
}
|
240
350
|
#elif OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
|
241
|
-
// Prior to OpenSSL 1.1.0, servers must manually enable server-side ECDH
|
242
|
-
// negotiation.
|
243
351
|
SSL_CTX_set_ecdh_auto(ctx, 1);
|
244
352
|
#endif
|
245
353
|
|
246
|
-
ssl = SSL_new(ctx);
|
247
|
-
conn->ssl = ssl;
|
248
|
-
SSL_set_app_data(ssl, NULL);
|
249
|
-
|
250
354
|
if (NIL_P(verify_mode)) {
|
251
|
-
/*
|
355
|
+
/* SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); */
|
252
356
|
} else {
|
253
|
-
|
357
|
+
SSL_CTX_set_verify(ctx, NUM2INT(verify_mode), engine_verify_callback);
|
254
358
|
}
|
255
359
|
|
256
|
-
|
360
|
+
// Random.bytes available in Ruby 2.5 and later, Random::DEFAULT deprecated in 3.0
|
361
|
+
session_id_bytes = rb_funcall(
|
362
|
+
#ifdef HAVE_RANDOM_BYTES
|
363
|
+
rb_cRandom,
|
364
|
+
#else
|
365
|
+
rb_const_get(rb_cRandom, rb_intern_const("DEFAULT")),
|
366
|
+
#endif
|
367
|
+
rb_intern_const("bytes"),
|
368
|
+
1, ULL2NUM(SSL_MAX_SSL_SESSION_ID_LENGTH));
|
369
|
+
|
370
|
+
SSL_CTX_set_session_id_context(ctx,
|
371
|
+
(unsigned char *) RSTRING_PTR(session_id_bytes),
|
372
|
+
SSL_MAX_SSL_SESSION_ID_LENGTH);
|
373
|
+
|
374
|
+
// printf("\ninitialize end security_level %d\n", SSL_CTX_get_security_level(ctx));
|
375
|
+
|
376
|
+
#ifdef HAVE_SSL_CTX_SET_DH_AUTO
|
377
|
+
// https://www.openssl.org/docs/man3.0/man3/SSL_CTX_set_dh_auto.html
|
378
|
+
SSL_CTX_set_dh_auto(ctx, 1);
|
379
|
+
#else
|
380
|
+
dh = get_dh2048();
|
381
|
+
SSL_CTX_set_tmp_dh(ctx, dh);
|
382
|
+
#endif
|
383
|
+
|
384
|
+
rb_obj_freeze(self);
|
385
|
+
return self;
|
386
|
+
}
|
257
387
|
|
388
|
+
VALUE engine_init_server(VALUE self, VALUE sslctx) {
|
389
|
+
ms_conn* conn;
|
390
|
+
VALUE obj;
|
391
|
+
SSL_CTX* ctx;
|
392
|
+
SSL* ssl;
|
393
|
+
|
394
|
+
conn = engine_alloc(self, &obj);
|
395
|
+
|
396
|
+
TypedData_Get_Struct(sslctx, SSL_CTX, &sslctx_type, ctx);
|
397
|
+
|
398
|
+
ssl = SSL_new(ctx);
|
399
|
+
conn->ssl = ssl;
|
400
|
+
SSL_set_app_data(ssl, NULL);
|
401
|
+
SSL_set_bio(ssl, conn->read, conn->write);
|
258
402
|
SSL_set_accept_state(ssl);
|
259
403
|
return obj;
|
260
404
|
}
|
@@ -281,7 +425,7 @@ VALUE engine_inject(VALUE self, VALUE str) {
|
|
281
425
|
ms_conn* conn;
|
282
426
|
long used;
|
283
427
|
|
284
|
-
|
428
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
285
429
|
|
286
430
|
StringValue(str);
|
287
431
|
|
@@ -294,13 +438,14 @@ VALUE engine_inject(VALUE self, VALUE str) {
|
|
294
438
|
return INT2FIX(used);
|
295
439
|
}
|
296
440
|
|
297
|
-
|
441
|
+
NORETURN(void raise_error(SSL* ssl, int result));
|
298
442
|
|
299
443
|
void raise_error(SSL* ssl, int result) {
|
300
444
|
char buf[512];
|
301
445
|
char msg[512];
|
302
446
|
const char* err_str;
|
303
447
|
int err = errno;
|
448
|
+
int mask = 4095;
|
304
449
|
int ssl_err = SSL_get_error(ssl, result);
|
305
450
|
int verify_err = (int) SSL_get_verify_result(ssl);
|
306
451
|
|
@@ -317,8 +462,7 @@ void raise_error(SSL* ssl, int result) {
|
|
317
462
|
} else {
|
318
463
|
err = (int) ERR_get_error();
|
319
464
|
ERR_error_string_n(err, buf, sizeof(buf));
|
320
|
-
snprintf(msg, sizeof(msg), "OpenSSL error: %s - %d", buf, err);
|
321
|
-
|
465
|
+
snprintf(msg, sizeof(msg), "OpenSSL error: %s - %d", buf, err & mask);
|
322
466
|
}
|
323
467
|
} else {
|
324
468
|
snprintf(msg, sizeof(msg), "Unknown OpenSSL error: %d", ssl_err);
|
@@ -333,7 +477,7 @@ VALUE engine_read(VALUE self) {
|
|
333
477
|
char buf[512];
|
334
478
|
int bytes, error;
|
335
479
|
|
336
|
-
|
480
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
337
481
|
|
338
482
|
ERR_clear_error();
|
339
483
|
|
@@ -360,7 +504,7 @@ VALUE engine_write(VALUE self, VALUE str) {
|
|
360
504
|
ms_conn* conn;
|
361
505
|
int bytes;
|
362
506
|
|
363
|
-
|
507
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
364
508
|
|
365
509
|
StringValue(str);
|
366
510
|
|
@@ -382,9 +526,11 @@ VALUE engine_extract(VALUE self) {
|
|
382
526
|
ms_conn* conn;
|
383
527
|
int bytes;
|
384
528
|
size_t pending;
|
385
|
-
|
529
|
+
// https://www.openssl.org/docs/manmaster/man3/BIO_f_buffer.html
|
530
|
+
// crypto/bio/bf_buff.c DEFAULT_BUFFER_SIZE
|
531
|
+
char buf[4096];
|
386
532
|
|
387
|
-
|
533
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
388
534
|
|
389
535
|
pending = BIO_pending(conn->write);
|
390
536
|
if(pending > 0) {
|
@@ -403,7 +549,7 @@ VALUE engine_shutdown(VALUE self) {
|
|
403
549
|
ms_conn* conn;
|
404
550
|
int ok;
|
405
551
|
|
406
|
-
|
552
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
407
553
|
|
408
554
|
ERR_clear_error();
|
409
555
|
|
@@ -418,7 +564,7 @@ VALUE engine_shutdown(VALUE self) {
|
|
418
564
|
VALUE engine_init(VALUE self) {
|
419
565
|
ms_conn* conn;
|
420
566
|
|
421
|
-
|
567
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
422
568
|
|
423
569
|
return SSL_in_init(conn->ssl) ? Qtrue : Qfalse;
|
424
570
|
}
|
@@ -431,9 +577,13 @@ VALUE engine_peercert(VALUE self) {
|
|
431
577
|
ms_cert_buf* cert_buf = NULL;
|
432
578
|
VALUE rb_cert_buf;
|
433
579
|
|
434
|
-
|
580
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
435
581
|
|
582
|
+
#ifdef HAVE_SSL_GET1_PEER_CERTIFICATE
|
583
|
+
cert = SSL_get1_peer_certificate(conn->ssl);
|
584
|
+
#else
|
436
585
|
cert = SSL_get_peer_certificate(conn->ssl);
|
586
|
+
#endif
|
437
587
|
if(!cert) {
|
438
588
|
/*
|
439
589
|
* See if there was a failed certificate associated with this client.
|
@@ -462,12 +612,22 @@ VALUE engine_peercert(VALUE self) {
|
|
462
612
|
return rb_cert_buf;
|
463
613
|
}
|
464
614
|
|
615
|
+
/* @see Puma::MiniSSL::Socket#ssl_version_state
|
616
|
+
* @version 5.0.0
|
617
|
+
*/
|
618
|
+
static VALUE
|
619
|
+
engine_ssl_vers_st(VALUE self) {
|
620
|
+
ms_conn* conn;
|
621
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
622
|
+
return rb_ary_new3(2, rb_str_new2(SSL_get_version(conn->ssl)), rb_str_new2(SSL_state_string(conn->ssl)));
|
623
|
+
}
|
624
|
+
|
465
625
|
VALUE noop(VALUE self) {
|
466
626
|
return Qnil;
|
467
627
|
}
|
468
628
|
|
469
629
|
void Init_mini_ssl(VALUE puma) {
|
470
|
-
VALUE mod, eng;
|
630
|
+
VALUE mod, eng, sslctx;
|
471
631
|
|
472
632
|
/* Fake operation for documentation (RDoc, YARD) */
|
473
633
|
#if 0 == 1
|
@@ -480,7 +640,15 @@ void Init_mini_ssl(VALUE puma) {
|
|
480
640
|
ERR_load_crypto_strings();
|
481
641
|
|
482
642
|
mod = rb_define_module_under(puma, "MiniSSL");
|
643
|
+
|
483
644
|
eng = rb_define_class_under(mod, "Engine", rb_cObject);
|
645
|
+
rb_undef_alloc_func(eng);
|
646
|
+
|
647
|
+
sslctx = rb_define_class_under(mod, "SSLContext", rb_cObject);
|
648
|
+
rb_define_alloc_func(sslctx, sslctx_alloc);
|
649
|
+
rb_define_method(sslctx, "initialize", sslctx_initialize, 1);
|
650
|
+
rb_undef_method(sslctx, "initialize_copy");
|
651
|
+
|
484
652
|
|
485
653
|
// OpenSSL Build / Runtime/Load versions
|
486
654
|
|
@@ -493,27 +661,27 @@ void Init_mini_ssl(VALUE puma) {
|
|
493
661
|
#else
|
494
662
|
rb_define_const(mod, "OPENSSL_LIBRARY_VERSION", rb_str_new2(SSLeay_version(SSLEAY_VERSION)));
|
495
663
|
#endif
|
496
|
-
|
497
|
-
#if defined(OPENSSL_NO_SSL3) || defined(OPENSSL_NO_SSL3_METHOD)
|
498
|
-
/* True if SSL3 is not available */
|
499
|
-
rb_define_const(mod, "OPENSSL_NO_SSL3", Qtrue);
|
500
|
-
#else
|
501
|
-
rb_define_const(mod, "OPENSSL_NO_SSL3", Qfalse);
|
502
|
-
#endif
|
503
|
-
|
504
|
-
#if defined(OPENSSL_NO_TLS1) || defined(OPENSSL_NO_TLS1_METHOD)
|
505
|
-
/* True if TLS1 is not available */
|
506
|
-
rb_define_const(mod, "OPENSSL_NO_TLS1", Qtrue);
|
507
|
-
#else
|
508
|
-
rb_define_const(mod, "OPENSSL_NO_TLS1", Qfalse);
|
509
|
-
#endif
|
510
|
-
|
511
|
-
#if defined(OPENSSL_NO_TLS1_1) || defined(OPENSSL_NO_TLS1_1_METHOD)
|
512
|
-
/* True if TLS1_1 is not available */
|
513
|
-
rb_define_const(mod, "OPENSSL_NO_TLS1_1", Qtrue);
|
514
|
-
#else
|
515
|
-
rb_define_const(mod, "OPENSSL_NO_TLS1_1", Qfalse);
|
516
|
-
#endif
|
664
|
+
|
665
|
+
#if defined(OPENSSL_NO_SSL3) || defined(OPENSSL_NO_SSL3_METHOD)
|
666
|
+
/* True if SSL3 is not available */
|
667
|
+
rb_define_const(mod, "OPENSSL_NO_SSL3", Qtrue);
|
668
|
+
#else
|
669
|
+
rb_define_const(mod, "OPENSSL_NO_SSL3", Qfalse);
|
670
|
+
#endif
|
671
|
+
|
672
|
+
#if defined(OPENSSL_NO_TLS1) || defined(OPENSSL_NO_TLS1_METHOD)
|
673
|
+
/* True if TLS1 is not available */
|
674
|
+
rb_define_const(mod, "OPENSSL_NO_TLS1", Qtrue);
|
675
|
+
#else
|
676
|
+
rb_define_const(mod, "OPENSSL_NO_TLS1", Qfalse);
|
677
|
+
#endif
|
678
|
+
|
679
|
+
#if defined(OPENSSL_NO_TLS1_1) || defined(OPENSSL_NO_TLS1_1_METHOD)
|
680
|
+
/* True if TLS1_1 is not available */
|
681
|
+
rb_define_const(mod, "OPENSSL_NO_TLS1_1", Qtrue);
|
682
|
+
#else
|
683
|
+
rb_define_const(mod, "OPENSSL_NO_TLS1_1", Qfalse);
|
684
|
+
#endif
|
517
685
|
|
518
686
|
rb_define_singleton_method(mod, "check", noop, 0);
|
519
687
|
|
@@ -533,13 +701,16 @@ void Init_mini_ssl(VALUE puma) {
|
|
533
701
|
rb_define_method(eng, "init?", engine_init, 0);
|
534
702
|
|
535
703
|
rb_define_method(eng, "peercert", engine_peercert, 0);
|
704
|
+
|
705
|
+
rb_define_method(eng, "ssl_vers_st", engine_ssl_vers_st, 0);
|
536
706
|
}
|
537
707
|
|
538
708
|
#else
|
539
709
|
|
710
|
+
NORETURN(VALUE raise_error(VALUE self));
|
711
|
+
|
540
712
|
VALUE raise_error(VALUE self) {
|
541
713
|
rb_raise(rb_eStandardError, "SSL not available in this build");
|
542
|
-
return Qnil;
|
543
714
|
}
|
544
715
|
|
545
716
|
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);
|
@@ -99,6 +99,8 @@ public class Http11 extends RubyObject {
|
|
99
99
|
int bite = b.get(i) & 0xFF;
|
100
100
|
if(bite == '-') {
|
101
101
|
b.set(i, (byte)'_');
|
102
|
+
} else if(bite == '_') {
|
103
|
+
b.set(i, (byte)',');
|
102
104
|
} else {
|
103
105
|
b.set(i, (byte)Character.toUpperCase(bite));
|
104
106
|
}
|
@@ -197,7 +199,7 @@ public class Http11 extends RubyObject {
|
|
197
199
|
validateMaxLength(runtime, parser.nread,MAX_HEADER_LENGTH, MAX_HEADER_LENGTH_ERR);
|
198
200
|
|
199
201
|
if(hp.has_error()) {
|
200
|
-
throw newHTTPParserError(runtime, "Invalid HTTP format, parsing fails.");
|
202
|
+
throw newHTTPParserError(runtime, "Invalid HTTP format, parsing fails. Are you trying to open an SSL connection to a non-SSL Puma?");
|
201
203
|
} else {
|
202
204
|
return runtime.newFixnum(parser.nread);
|
203
205
|
}
|