puma 3.12.1 → 5.6.4
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 +1553 -447
- data/LICENSE +23 -20
- data/README.md +175 -63
- data/bin/puma-wild +3 -9
- data/docs/architecture.md +59 -21
- data/docs/compile_options.md +21 -0
- data/docs/deployment.md +69 -58
- data/docs/fork_worker.md +33 -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 +1 -1
- 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 +95 -120
- data/ext/puma_http11/PumaHttp11Service.java +2 -2
- data/ext/puma_http11/ext_help.h +1 -1
- data/ext/puma_http11/extconf.rb +51 -1
- data/ext/puma_http11/http11_parser.c +105 -117
- data/ext/puma_http11/http11_parser.h +1 -1
- data/ext/puma_http11/http11_parser.java.rl +22 -38
- data/ext/puma_http11/http11_parser.rl +4 -2
- data/ext/puma_http11/http11_parser_common.rl +4 -4
- data/ext/puma_http11/mini_ssl.c +319 -96
- 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 +120 -65
- data/ext/puma_http11/puma_http11.c +35 -51
- data/lib/puma/app/status.rb +68 -49
- data/lib/puma/binder.rb +234 -137
- data/lib/puma/cli.rb +28 -18
- data/lib/puma/client.rb +343 -230
- data/lib/puma/cluster/worker.rb +173 -0
- data/lib/puma/cluster/worker_handle.rb +94 -0
- data/lib/puma/cluster.rb +247 -232
- data/lib/puma/commonlogger.rb +2 -2
- data/lib/puma/configuration.rb +61 -51
- data/lib/puma/const.rb +42 -21
- data/lib/puma/control_cli.rb +109 -67
- data/lib/puma/detect.rb +29 -2
- data/lib/puma/dsl.rb +615 -123
- data/lib/puma/error_logger.rb +104 -0
- data/lib/puma/events.rb +55 -31
- data/lib/puma/io_buffer.rb +7 -5
- data/lib/puma/jruby_restart.rb +0 -58
- data/lib/puma/json_serialization.rb +96 -0
- data/lib/puma/launcher.rb +182 -69
- data/lib/puma/minissl/context_builder.rb +81 -0
- data/lib/puma/minissl.rb +161 -61
- data/lib/puma/null_io.rb +13 -1
- data/lib/puma/plugin/tmp_restart.rb +2 -0
- data/lib/puma/plugin.rb +7 -13
- data/lib/puma/queue_close.rb +26 -0
- data/lib/puma/rack/builder.rb +3 -5
- data/lib/puma/rack/urlmap.rb +2 -0
- data/lib/puma/rack_default.rb +2 -0
- data/lib/puma/reactor.rb +85 -316
- data/lib/puma/request.rb +472 -0
- data/lib/puma/runner.rb +48 -55
- data/lib/puma/server.rb +303 -695
- data/lib/puma/single.rb +11 -67
- data/lib/puma/state_file.rb +47 -8
- data/lib/puma/systemd.rb +46 -0
- data/lib/puma/thread_pool.rb +132 -82
- data/lib/puma/util.rb +21 -7
- data/lib/puma.rb +54 -0
- data/lib/rack/handler/puma.rb +5 -6
- data/tools/Dockerfile +16 -0
- data/tools/trickletest.rb +0 -1
- metadata +45 -29
- 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
@@ -1,5 +1,5 @@
|
|
1
1
|
%%{
|
2
|
-
|
2
|
+
|
3
3
|
machine puma_parser_common;
|
4
4
|
|
5
5
|
#### HTTP PROTOCOL GRAMMAR
|
@@ -16,7 +16,7 @@
|
|
16
16
|
unreserved = (alpha | digit | safe | extra | national);
|
17
17
|
escape = ("%" xdigit xdigit);
|
18
18
|
uchar = (unreserved | escape | "%");
|
19
|
-
pchar = (uchar | ":" | "@" | "&" | "=" | "+");
|
19
|
+
pchar = (uchar | ":" | "@" | "&" | "=" | "+" | ";");
|
20
20
|
tspecials = ("(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\\" | "\"" | "/" | "[" | "]" | "?" | "=" | "{" | "}" | " " | "\t");
|
21
21
|
|
22
22
|
# elements
|
@@ -30,7 +30,7 @@
|
|
30
30
|
query = ( uchar | reserved )* %query_string ;
|
31
31
|
param = ( pchar | "/" )* ;
|
32
32
|
params = ( param ( ";" param )* ) ;
|
33
|
-
rel_path = ( path? %request_path
|
33
|
+
rel_path = ( path? %request_path ) ("?" %start_query query)?;
|
34
34
|
absolute_path = ( "/"+ rel_path );
|
35
35
|
|
36
36
|
Request_URI = ( "*" | absolute_uri | absolute_path ) >mark %request_uri;
|
@@ -43,7 +43,7 @@
|
|
43
43
|
|
44
44
|
field_name = ( token -- ":" )+ >start_field $snake_upcase_field %write_field;
|
45
45
|
|
46
|
-
field_value = any* >start_value %write_value;
|
46
|
+
field_value = ( (any -- CTL) | "\t" )* >start_value %write_value;
|
47
47
|
|
48
48
|
message_header = field_name ":" " "* field_value :> CRLF;
|
49
49
|
|
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,10 @@ typedef struct {
|
|
33
28
|
int bytes;
|
34
29
|
} ms_cert_buf;
|
35
30
|
|
36
|
-
|
31
|
+
VALUE eError;
|
32
|
+
|
33
|
+
void engine_free(void *ptr) {
|
34
|
+
ms_conn *conn = ptr;
|
37
35
|
ms_cert_buf* cert_buf = (ms_cert_buf*)SSL_get_app_data(conn->ssl);
|
38
36
|
if(cert_buf) {
|
39
37
|
OPENSSL_free(cert_buf->buf);
|
@@ -45,61 +43,72 @@ void engine_free(ms_conn* conn) {
|
|
45
43
|
free(conn);
|
46
44
|
}
|
47
45
|
|
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);
|
46
|
+
const rb_data_type_t engine_data_type = {
|
47
|
+
"MiniSSL/ENGINE",
|
48
|
+
{ 0, engine_free, 0 },
|
49
|
+
0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
|
50
|
+
};
|
58
51
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
return conn;
|
63
|
-
}
|
64
|
-
|
65
|
-
DH *get_dh1024() {
|
66
|
-
/* `openssl dhparam 1024 -C`
|
52
|
+
#ifndef HAVE_SSL_GET1_PEER_CERTIFICATE
|
53
|
+
DH *get_dh2048(void) {
|
54
|
+
/* `openssl dhparam -C 2048`
|
67
55
|
* -----BEGIN DH PARAMETERS-----
|
68
|
-
*
|
69
|
-
*
|
70
|
-
*
|
56
|
+
* MIIBCAKCAQEAjmh1uQHdTfxOyxEbKAV30fUfzqMDF/ChPzjfyzl2jcrqQMhrk76o
|
57
|
+
* 2NPNXqxHwsddMZ1RzvU8/jl+uhRuPWjXCFZbhET4N1vrviZM3VJhV8PPHuiVOACO
|
58
|
+
* y32jFd+Szx4bo2cXSK83hJ6jRd+0asP1awWjz9/06dFkrILCXMIfQLo0D8rqmppn
|
59
|
+
* EfDDAwuudCpM9kcDmBRAm9JsKbQ6gzZWjkc5+QWSaQofojIHbjvj3xzguaCJn+oQ
|
60
|
+
* vHWM+hsAnaOgEwCyeZ3xqs+/5lwSbkE/tqJW98cEZGygBUVo9jxZRZx6KOfjpdrb
|
61
|
+
* yenO9LJr/qtyrZB31WJbqxI0m0AKTAO8UwIBAg==
|
71
62
|
* -----END DH PARAMETERS-----
|
72
63
|
*/
|
73
|
-
static unsigned char
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
64
|
+
static unsigned char dh2048_p[] = {
|
65
|
+
0x8E, 0x68, 0x75, 0xB9, 0x01, 0xDD, 0x4D, 0xFC, 0x4E, 0xCB,
|
66
|
+
0x11, 0x1B, 0x28, 0x05, 0x77, 0xD1, 0xF5, 0x1F, 0xCE, 0xA3,
|
67
|
+
0x03, 0x17, 0xF0, 0xA1, 0x3F, 0x38, 0xDF, 0xCB, 0x39, 0x76,
|
68
|
+
0x8D, 0xCA, 0xEA, 0x40, 0xC8, 0x6B, 0x93, 0xBE, 0xA8, 0xD8,
|
69
|
+
0xD3, 0xCD, 0x5E, 0xAC, 0x47, 0xC2, 0xC7, 0x5D, 0x31, 0x9D,
|
70
|
+
0x51, 0xCE, 0xF5, 0x3C, 0xFE, 0x39, 0x7E, 0xBA, 0x14, 0x6E,
|
71
|
+
0x3D, 0x68, 0xD7, 0x08, 0x56, 0x5B, 0x84, 0x44, 0xF8, 0x37,
|
72
|
+
0x5B, 0xEB, 0xBE, 0x26, 0x4C, 0xDD, 0x52, 0x61, 0x57, 0xC3,
|
73
|
+
0xCF, 0x1E, 0xE8, 0x95, 0x38, 0x00, 0x8E, 0xCB, 0x7D, 0xA3,
|
74
|
+
0x15, 0xDF, 0x92, 0xCF, 0x1E, 0x1B, 0xA3, 0x67, 0x17, 0x48,
|
75
|
+
0xAF, 0x37, 0x84, 0x9E, 0xA3, 0x45, 0xDF, 0xB4, 0x6A, 0xC3,
|
76
|
+
0xF5, 0x6B, 0x05, 0xA3, 0xCF, 0xDF, 0xF4, 0xE9, 0xD1, 0x64,
|
77
|
+
0xAC, 0x82, 0xC2, 0x5C, 0xC2, 0x1F, 0x40, 0xBA, 0x34, 0x0F,
|
78
|
+
0xCA, 0xEA, 0x9A, 0x9A, 0x67, 0x11, 0xF0, 0xC3, 0x03, 0x0B,
|
79
|
+
0xAE, 0x74, 0x2A, 0x4C, 0xF6, 0x47, 0x03, 0x98, 0x14, 0x40,
|
80
|
+
0x9B, 0xD2, 0x6C, 0x29, 0xB4, 0x3A, 0x83, 0x36, 0x56, 0x8E,
|
81
|
+
0x47, 0x39, 0xF9, 0x05, 0x92, 0x69, 0x0A, 0x1F, 0xA2, 0x32,
|
82
|
+
0x07, 0x6E, 0x3B, 0xE3, 0xDF, 0x1C, 0xE0, 0xB9, 0xA0, 0x89,
|
83
|
+
0x9F, 0xEA, 0x10, 0xBC, 0x75, 0x8C, 0xFA, 0x1B, 0x00, 0x9D,
|
84
|
+
0xA3, 0xA0, 0x13, 0x00, 0xB2, 0x79, 0x9D, 0xF1, 0xAA, 0xCF,
|
85
|
+
0xBF, 0xE6, 0x5C, 0x12, 0x6E, 0x41, 0x3F, 0xB6, 0xA2, 0x56,
|
86
|
+
0xF7, 0xC7, 0x04, 0x64, 0x6C, 0xA0, 0x05, 0x45, 0x68, 0xF6,
|
87
|
+
0x3C, 0x59, 0x45, 0x9C, 0x7A, 0x28, 0xE7, 0xE3, 0xA5, 0xDA,
|
88
|
+
0xDB, 0xC9, 0xE9, 0xCE, 0xF4, 0xB2, 0x6B, 0xFE, 0xAB, 0x72,
|
89
|
+
0xAD, 0x90, 0x77, 0xD5, 0x62, 0x5B, 0xAB, 0x12, 0x34, 0x9B,
|
90
|
+
0x40, 0x0A, 0x4C, 0x03, 0xBC, 0x53
|
85
91
|
};
|
86
|
-
static unsigned char
|
92
|
+
static unsigned char dh2048_g[] = { 0x02 };
|
87
93
|
|
88
94
|
DH *dh;
|
95
|
+
#if !(OPENSSL_VERSION_NUMBER < 0x10100005L || defined(LIBRESSL_VERSION_NUMBER))
|
96
|
+
BIGNUM *p, *g;
|
97
|
+
#endif
|
98
|
+
|
89
99
|
dh = DH_new();
|
90
100
|
|
91
101
|
#if OPENSSL_VERSION_NUMBER < 0x10100005L || defined(LIBRESSL_VERSION_NUMBER)
|
92
|
-
dh->p = BN_bin2bn(
|
93
|
-
dh->g = BN_bin2bn(
|
102
|
+
dh->p = BN_bin2bn(dh2048_p, sizeof(dh2048_p), NULL);
|
103
|
+
dh->g = BN_bin2bn(dh2048_g, sizeof(dh2048_g), NULL);
|
94
104
|
|
95
105
|
if ((dh->p == NULL) || (dh->g == NULL)) {
|
96
106
|
DH_free(dh);
|
97
107
|
return NULL;
|
98
108
|
}
|
99
109
|
#else
|
100
|
-
|
101
|
-
|
102
|
-
g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
|
110
|
+
p = BN_bin2bn(dh2048_p, sizeof(dh2048_p), NULL);
|
111
|
+
g = BN_bin2bn(dh2048_g, sizeof(dh2048_g), NULL);
|
103
112
|
|
104
113
|
if (p == NULL || g == NULL || !DH_set0_pqg(dh, p, NULL, g)) {
|
105
114
|
DH_free(dh);
|
@@ -111,6 +120,38 @@ DH *get_dh1024() {
|
|
111
120
|
|
112
121
|
return dh;
|
113
122
|
}
|
123
|
+
#endif
|
124
|
+
|
125
|
+
static void
|
126
|
+
sslctx_free(void *ptr) {
|
127
|
+
SSL_CTX *ctx = ptr;
|
128
|
+
SSL_CTX_free(ctx);
|
129
|
+
}
|
130
|
+
|
131
|
+
static const rb_data_type_t sslctx_type = {
|
132
|
+
"MiniSSL/SSLContext",
|
133
|
+
{
|
134
|
+
0, sslctx_free,
|
135
|
+
},
|
136
|
+
0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
|
137
|
+
};
|
138
|
+
|
139
|
+
ms_conn* engine_alloc(VALUE klass, VALUE* obj) {
|
140
|
+
ms_conn* conn;
|
141
|
+
|
142
|
+
*obj = TypedData_Make_Struct(klass, ms_conn, &engine_data_type, conn);
|
143
|
+
|
144
|
+
conn->read = BIO_new(BIO_s_mem());
|
145
|
+
BIO_set_nbio(conn->read, 1);
|
146
|
+
|
147
|
+
conn->write = BIO_new(BIO_s_mem());
|
148
|
+
BIO_set_nbio(conn->write, 1);
|
149
|
+
|
150
|
+
conn->ssl = 0;
|
151
|
+
conn->ctx = 0;
|
152
|
+
|
153
|
+
return conn;
|
154
|
+
}
|
114
155
|
|
115
156
|
static int engine_verify_callback(int preverify_ok, X509_STORE_CTX* ctx) {
|
116
157
|
X509* err_cert;
|
@@ -138,44 +179,138 @@ static int engine_verify_callback(int preverify_ok, X509_STORE_CTX* ctx) {
|
|
138
179
|
return preverify_ok;
|
139
180
|
}
|
140
181
|
|
141
|
-
|
142
|
-
|
182
|
+
static VALUE
|
183
|
+
sslctx_alloc(VALUE klass) {
|
184
|
+
SSL_CTX *ctx;
|
185
|
+
long mode = 0 |
|
186
|
+
SSL_MODE_ENABLE_PARTIAL_WRITE |
|
187
|
+
SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
|
188
|
+
SSL_MODE_RELEASE_BUFFERS;
|
189
|
+
|
190
|
+
#ifdef HAVE_TLS_SERVER_METHOD
|
191
|
+
ctx = SSL_CTX_new(TLS_method());
|
192
|
+
// printf("\nctx using TLS_method security_level %d\n", SSL_CTX_get_security_level(ctx));
|
193
|
+
#else
|
194
|
+
ctx = SSL_CTX_new(SSLv23_method());
|
195
|
+
#endif
|
196
|
+
if (!ctx) {
|
197
|
+
rb_raise(eError, "SSL_CTX_new");
|
198
|
+
}
|
199
|
+
SSL_CTX_set_mode(ctx, mode);
|
200
|
+
|
201
|
+
return TypedData_Wrap_Struct(klass, &sslctx_type, ctx);
|
202
|
+
}
|
203
|
+
|
204
|
+
VALUE
|
205
|
+
sslctx_initialize(VALUE self, VALUE mini_ssl_ctx) {
|
143
206
|
SSL_CTX* ctx;
|
144
|
-
SSL* ssl;
|
145
207
|
|
146
|
-
|
208
|
+
#ifdef HAVE_SSL_CTX_SET_MIN_PROTO_VERSION
|
209
|
+
int min;
|
210
|
+
#endif
|
211
|
+
int ssl_options;
|
212
|
+
VALUE key, cert, ca, verify_mode, ssl_cipher_filter, no_tlsv1, no_tlsv1_1,
|
213
|
+
verification_flags, session_id_bytes, cert_pem, key_pem;
|
214
|
+
#ifndef HAVE_SSL_GET1_PEER_CERTIFICATE
|
215
|
+
DH *dh;
|
216
|
+
#endif
|
217
|
+
BIO *bio;
|
218
|
+
X509 *x509;
|
219
|
+
EVP_PKEY *pkey;
|
220
|
+
|
221
|
+
#if OPENSSL_VERSION_NUMBER < 0x10002000L
|
222
|
+
EC_KEY *ecdh;
|
223
|
+
#endif
|
224
|
+
|
225
|
+
TypedData_Get_Struct(self, SSL_CTX, &sslctx_type, ctx);
|
147
226
|
|
148
|
-
|
149
|
-
VALUE key = rb_funcall(mini_ssl_ctx, sym_key, 0);
|
227
|
+
key = rb_funcall(mini_ssl_ctx, rb_intern_const("key"), 0);
|
150
228
|
|
151
|
-
|
229
|
+
cert = rb_funcall(mini_ssl_ctx, rb_intern_const("cert"), 0);
|
152
230
|
|
153
|
-
|
154
|
-
VALUE cert = rb_funcall(mini_ssl_ctx, sym_cert, 0);
|
231
|
+
ca = rb_funcall(mini_ssl_ctx, rb_intern_const("ca"), 0);
|
155
232
|
|
156
|
-
|
233
|
+
cert_pem = rb_funcall(mini_ssl_ctx, rb_intern_const("cert_pem"), 0);
|
157
234
|
|
158
|
-
|
159
|
-
VALUE ca = rb_funcall(mini_ssl_ctx, sym_ca, 0);
|
235
|
+
key_pem = rb_funcall(mini_ssl_ctx, rb_intern_const("key_pem"), 0);
|
160
236
|
|
161
|
-
|
162
|
-
VALUE verify_mode = rb_funcall(mini_ssl_ctx, sym_verify_mode, 0);
|
237
|
+
verify_mode = rb_funcall(mini_ssl_ctx, rb_intern_const("verify_mode"), 0);
|
163
238
|
|
164
|
-
|
165
|
-
VALUE ssl_cipher_filter = rb_funcall(mini_ssl_ctx, sym_ssl_cipher_filter, 0);
|
239
|
+
ssl_cipher_filter = rb_funcall(mini_ssl_ctx, rb_intern_const("ssl_cipher_filter"), 0);
|
166
240
|
|
167
|
-
|
168
|
-
conn->ctx = ctx;
|
241
|
+
no_tlsv1 = rb_funcall(mini_ssl_ctx, rb_intern_const("no_tlsv1"), 0);
|
169
242
|
|
170
|
-
|
171
|
-
|
243
|
+
no_tlsv1_1 = rb_funcall(mini_ssl_ctx, rb_intern_const("no_tlsv1_1"), 0);
|
244
|
+
|
245
|
+
if (!NIL_P(cert)) {
|
246
|
+
StringValue(cert);
|
247
|
+
SSL_CTX_use_certificate_chain_file(ctx, RSTRING_PTR(cert));
|
248
|
+
}
|
249
|
+
|
250
|
+
if (!NIL_P(key)) {
|
251
|
+
StringValue(key);
|
252
|
+
SSL_CTX_use_PrivateKey_file(ctx, RSTRING_PTR(key), SSL_FILETYPE_PEM);
|
253
|
+
}
|
254
|
+
|
255
|
+
if (!NIL_P(cert_pem)) {
|
256
|
+
bio = BIO_new(BIO_s_mem());
|
257
|
+
BIO_puts(bio, RSTRING_PTR(cert_pem));
|
258
|
+
x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
|
259
|
+
|
260
|
+
SSL_CTX_use_certificate(ctx, x509);
|
261
|
+
}
|
262
|
+
|
263
|
+
if (!NIL_P(key_pem)) {
|
264
|
+
bio = BIO_new(BIO_s_mem());
|
265
|
+
BIO_puts(bio, RSTRING_PTR(key_pem));
|
266
|
+
pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
|
267
|
+
|
268
|
+
SSL_CTX_use_PrivateKey(ctx, pkey);
|
269
|
+
}
|
270
|
+
|
271
|
+
verification_flags = rb_funcall(mini_ssl_ctx, rb_intern_const("verification_flags"), 0);
|
272
|
+
|
273
|
+
if (!NIL_P(verification_flags)) {
|
274
|
+
X509_VERIFY_PARAM *param = SSL_CTX_get0_param(ctx);
|
275
|
+
X509_VERIFY_PARAM_set_flags(param, NUM2INT(verification_flags));
|
276
|
+
SSL_CTX_set1_param(ctx, param);
|
277
|
+
}
|
172
278
|
|
173
279
|
if (!NIL_P(ca)) {
|
174
280
|
StringValue(ca);
|
175
281
|
SSL_CTX_load_verify_locations(ctx, RSTRING_PTR(ca), NULL);
|
176
282
|
}
|
177
283
|
|
178
|
-
|
284
|
+
ssl_options = SSL_OP_CIPHER_SERVER_PREFERENCE | SSL_OP_SINGLE_ECDH_USE | SSL_OP_NO_COMPRESSION;
|
285
|
+
|
286
|
+
#ifdef HAVE_SSL_CTX_SET_MIN_PROTO_VERSION
|
287
|
+
if (RTEST(no_tlsv1_1)) {
|
288
|
+
min = TLS1_2_VERSION;
|
289
|
+
}
|
290
|
+
else if (RTEST(no_tlsv1)) {
|
291
|
+
min = TLS1_1_VERSION;
|
292
|
+
}
|
293
|
+
else {
|
294
|
+
min = TLS1_VERSION;
|
295
|
+
}
|
296
|
+
|
297
|
+
SSL_CTX_set_min_proto_version(ctx, min);
|
298
|
+
|
299
|
+
SSL_CTX_set_options(ctx, ssl_options);
|
300
|
+
|
301
|
+
#else
|
302
|
+
/* As of 1.0.2f, SSL_OP_SINGLE_DH_USE key use is always on */
|
303
|
+
ssl_options |= SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_SINGLE_DH_USE;
|
304
|
+
|
305
|
+
if (RTEST(no_tlsv1)) {
|
306
|
+
ssl_options |= SSL_OP_NO_TLSv1;
|
307
|
+
}
|
308
|
+
if(RTEST(no_tlsv1_1)) {
|
309
|
+
ssl_options |= SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1;
|
310
|
+
}
|
311
|
+
SSL_CTX_set_options(ctx, ssl_options);
|
312
|
+
#endif
|
313
|
+
|
179
314
|
SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
|
180
315
|
|
181
316
|
if (!NIL_P(ssl_cipher_filter)) {
|
@@ -186,29 +321,66 @@ VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) {
|
|
186
321
|
SSL_CTX_set_cipher_list(ctx, "HIGH:!aNULL@STRENGTH");
|
187
322
|
}
|
188
323
|
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_secp521r1);
|
324
|
+
#if OPENSSL_VERSION_NUMBER < 0x10002000L
|
325
|
+
// Remove this case if OpenSSL 1.0.1 (now EOL) support is no
|
326
|
+
// longer needed.
|
327
|
+
ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
|
194
328
|
if (ecdh) {
|
195
329
|
SSL_CTX_set_tmp_ecdh(ctx, ecdh);
|
196
330
|
EC_KEY_free(ecdh);
|
197
331
|
}
|
332
|
+
#elif OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
|
333
|
+
SSL_CTX_set_ecdh_auto(ctx, 1);
|
198
334
|
#endif
|
199
335
|
|
200
|
-
ssl = SSL_new(ctx);
|
201
|
-
conn->ssl = ssl;
|
202
|
-
SSL_set_app_data(ssl, NULL);
|
203
|
-
|
204
336
|
if (NIL_P(verify_mode)) {
|
205
|
-
/*
|
337
|
+
/* SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); */
|
206
338
|
} else {
|
207
|
-
|
339
|
+
SSL_CTX_set_verify(ctx, NUM2INT(verify_mode), engine_verify_callback);
|
208
340
|
}
|
209
341
|
|
210
|
-
|
342
|
+
// Random.bytes available in Ruby 2.5 and later, Random::DEFAULT deprecated in 3.0
|
343
|
+
session_id_bytes = rb_funcall(
|
344
|
+
#ifdef HAVE_RANDOM_BYTES
|
345
|
+
rb_cRandom,
|
346
|
+
#else
|
347
|
+
rb_const_get(rb_cRandom, rb_intern_const("DEFAULT")),
|
348
|
+
#endif
|
349
|
+
rb_intern_const("bytes"),
|
350
|
+
1, ULL2NUM(SSL_MAX_SSL_SESSION_ID_LENGTH));
|
351
|
+
|
352
|
+
SSL_CTX_set_session_id_context(ctx,
|
353
|
+
(unsigned char *) RSTRING_PTR(session_id_bytes),
|
354
|
+
SSL_MAX_SSL_SESSION_ID_LENGTH);
|
355
|
+
|
356
|
+
// printf("\ninitialize end security_level %d\n", SSL_CTX_get_security_level(ctx));
|
357
|
+
|
358
|
+
#ifdef HAVE_SSL_GET1_PEER_CERTIFICATE
|
359
|
+
// https://www.openssl.org/docs/man3.0/man3/SSL_CTX_set_dh_auto.html
|
360
|
+
SSL_CTX_set_dh_auto(ctx, 1);
|
361
|
+
#else
|
362
|
+
dh = get_dh2048();
|
363
|
+
SSL_CTX_set_tmp_dh(ctx, dh);
|
364
|
+
#endif
|
365
|
+
|
366
|
+
rb_obj_freeze(self);
|
367
|
+
return self;
|
368
|
+
}
|
369
|
+
|
370
|
+
VALUE engine_init_server(VALUE self, VALUE sslctx) {
|
371
|
+
ms_conn* conn;
|
372
|
+
VALUE obj;
|
373
|
+
SSL_CTX* ctx;
|
374
|
+
SSL* ssl;
|
375
|
+
|
376
|
+
conn = engine_alloc(self, &obj);
|
377
|
+
|
378
|
+
TypedData_Get_Struct(sslctx, SSL_CTX, &sslctx_type, ctx);
|
211
379
|
|
380
|
+
ssl = SSL_new(ctx);
|
381
|
+
conn->ssl = ssl;
|
382
|
+
SSL_set_app_data(ssl, NULL);
|
383
|
+
SSL_set_bio(ssl, conn->read, conn->write);
|
212
384
|
SSL_set_accept_state(ssl);
|
213
385
|
return obj;
|
214
386
|
}
|
@@ -216,8 +388,11 @@ VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) {
|
|
216
388
|
VALUE engine_init_client(VALUE klass) {
|
217
389
|
VALUE obj;
|
218
390
|
ms_conn* conn = engine_alloc(klass, &obj);
|
219
|
-
|
391
|
+
#ifdef HAVE_DTLS_METHOD
|
392
|
+
conn->ctx = SSL_CTX_new(DTLS_method());
|
393
|
+
#else
|
220
394
|
conn->ctx = SSL_CTX_new(DTLSv1_method());
|
395
|
+
#endif
|
221
396
|
conn->ssl = SSL_new(conn->ctx);
|
222
397
|
SSL_set_app_data(conn->ssl, NULL);
|
223
398
|
SSL_set_verify(conn->ssl, SSL_VERIFY_NONE, NULL);
|
@@ -232,7 +407,7 @@ VALUE engine_inject(VALUE self, VALUE str) {
|
|
232
407
|
ms_conn* conn;
|
233
408
|
long used;
|
234
409
|
|
235
|
-
|
410
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
236
411
|
|
237
412
|
StringValue(str);
|
238
413
|
|
@@ -245,13 +420,14 @@ VALUE engine_inject(VALUE self, VALUE str) {
|
|
245
420
|
return INT2FIX(used);
|
246
421
|
}
|
247
422
|
|
248
|
-
|
423
|
+
NORETURN(void raise_error(SSL* ssl, int result));
|
249
424
|
|
250
425
|
void raise_error(SSL* ssl, int result) {
|
251
426
|
char buf[512];
|
252
427
|
char msg[512];
|
253
428
|
const char* err_str;
|
254
429
|
int err = errno;
|
430
|
+
int mask = 4095;
|
255
431
|
int ssl_err = SSL_get_error(ssl, result);
|
256
432
|
int verify_err = (int) SSL_get_verify_result(ssl);
|
257
433
|
|
@@ -268,8 +444,7 @@ void raise_error(SSL* ssl, int result) {
|
|
268
444
|
} else {
|
269
445
|
err = (int) ERR_get_error();
|
270
446
|
ERR_error_string_n(err, buf, sizeof(buf));
|
271
|
-
snprintf(msg, sizeof(msg), "OpenSSL error: %s - %d", buf, err);
|
272
|
-
|
447
|
+
snprintf(msg, sizeof(msg), "OpenSSL error: %s - %d", buf, err & mask);
|
273
448
|
}
|
274
449
|
} else {
|
275
450
|
snprintf(msg, sizeof(msg), "Unknown OpenSSL error: %d", ssl_err);
|
@@ -284,7 +459,7 @@ VALUE engine_read(VALUE self) {
|
|
284
459
|
char buf[512];
|
285
460
|
int bytes, error;
|
286
461
|
|
287
|
-
|
462
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
288
463
|
|
289
464
|
ERR_clear_error();
|
290
465
|
|
@@ -311,7 +486,7 @@ VALUE engine_write(VALUE self, VALUE str) {
|
|
311
486
|
ms_conn* conn;
|
312
487
|
int bytes;
|
313
488
|
|
314
|
-
|
489
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
315
490
|
|
316
491
|
StringValue(str);
|
317
492
|
|
@@ -333,9 +508,11 @@ VALUE engine_extract(VALUE self) {
|
|
333
508
|
ms_conn* conn;
|
334
509
|
int bytes;
|
335
510
|
size_t pending;
|
336
|
-
|
511
|
+
// https://www.openssl.org/docs/manmaster/man3/BIO_f_buffer.html
|
512
|
+
// crypto/bio/bf_buff.c DEFAULT_BUFFER_SIZE
|
513
|
+
char buf[4096];
|
337
514
|
|
338
|
-
|
515
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
339
516
|
|
340
517
|
pending = BIO_pending(conn->write);
|
341
518
|
if(pending > 0) {
|
@@ -354,7 +531,7 @@ VALUE engine_shutdown(VALUE self) {
|
|
354
531
|
ms_conn* conn;
|
355
532
|
int ok;
|
356
533
|
|
357
|
-
|
534
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
358
535
|
|
359
536
|
ERR_clear_error();
|
360
537
|
|
@@ -369,7 +546,7 @@ VALUE engine_shutdown(VALUE self) {
|
|
369
546
|
VALUE engine_init(VALUE self) {
|
370
547
|
ms_conn* conn;
|
371
548
|
|
372
|
-
|
549
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
373
550
|
|
374
551
|
return SSL_in_init(conn->ssl) ? Qtrue : Qfalse;
|
375
552
|
}
|
@@ -382,9 +559,13 @@ VALUE engine_peercert(VALUE self) {
|
|
382
559
|
ms_cert_buf* cert_buf = NULL;
|
383
560
|
VALUE rb_cert_buf;
|
384
561
|
|
385
|
-
|
562
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
386
563
|
|
564
|
+
#ifdef HAVE_SSL_GET1_PEER_CERTIFICATE
|
565
|
+
cert = SSL_get1_peer_certificate(conn->ssl);
|
566
|
+
#else
|
387
567
|
cert = SSL_get_peer_certificate(conn->ssl);
|
568
|
+
#endif
|
388
569
|
if(!cert) {
|
389
570
|
/*
|
390
571
|
* See if there was a failed certificate associated with this client.
|
@@ -413,12 +594,22 @@ VALUE engine_peercert(VALUE self) {
|
|
413
594
|
return rb_cert_buf;
|
414
595
|
}
|
415
596
|
|
597
|
+
/* @see Puma::MiniSSL::Socket#ssl_version_state
|
598
|
+
* @version 5.0.0
|
599
|
+
*/
|
600
|
+
static VALUE
|
601
|
+
engine_ssl_vers_st(VALUE self) {
|
602
|
+
ms_conn* conn;
|
603
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
604
|
+
return rb_ary_new3(2, rb_str_new2(SSL_get_version(conn->ssl)), rb_str_new2(SSL_state_string(conn->ssl)));
|
605
|
+
}
|
606
|
+
|
416
607
|
VALUE noop(VALUE self) {
|
417
608
|
return Qnil;
|
418
609
|
}
|
419
610
|
|
420
611
|
void Init_mini_ssl(VALUE puma) {
|
421
|
-
VALUE mod, eng;
|
612
|
+
VALUE mod, eng, sslctx;
|
422
613
|
|
423
614
|
/* Fake operation for documentation (RDoc, YARD) */
|
424
615
|
#if 0 == 1
|
@@ -431,18 +622,47 @@ void Init_mini_ssl(VALUE puma) {
|
|
431
622
|
ERR_load_crypto_strings();
|
432
623
|
|
433
624
|
mod = rb_define_module_under(puma, "MiniSSL");
|
625
|
+
|
434
626
|
eng = rb_define_class_under(mod, "Engine", rb_cObject);
|
627
|
+
rb_undef_alloc_func(eng);
|
628
|
+
|
629
|
+
sslctx = rb_define_class_under(mod, "SSLContext", rb_cObject);
|
630
|
+
rb_define_alloc_func(sslctx, sslctx_alloc);
|
631
|
+
rb_define_method(sslctx, "initialize", sslctx_initialize, 1);
|
632
|
+
rb_undef_method(sslctx, "initialize_copy");
|
633
|
+
|
435
634
|
|
436
635
|
// OpenSSL Build / Runtime/Load versions
|
437
636
|
|
438
637
|
/* Version of OpenSSL that Puma was compiled with */
|
439
|
-
|
638
|
+
rb_define_const(mod, "OPENSSL_VERSION", rb_str_new2(OPENSSL_VERSION_TEXT));
|
440
639
|
|
441
640
|
#if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000
|
442
|
-
|
443
|
-
|
641
|
+
/* Version of OpenSSL that Puma loaded with */
|
642
|
+
rb_define_const(mod, "OPENSSL_LIBRARY_VERSION", rb_str_new2(OpenSSL_version(OPENSSL_VERSION)));
|
444
643
|
#else
|
445
|
-
|
644
|
+
rb_define_const(mod, "OPENSSL_LIBRARY_VERSION", rb_str_new2(SSLeay_version(SSLEAY_VERSION)));
|
645
|
+
#endif
|
646
|
+
|
647
|
+
#if defined(OPENSSL_NO_SSL3) || defined(OPENSSL_NO_SSL3_METHOD)
|
648
|
+
/* True if SSL3 is not available */
|
649
|
+
rb_define_const(mod, "OPENSSL_NO_SSL3", Qtrue);
|
650
|
+
#else
|
651
|
+
rb_define_const(mod, "OPENSSL_NO_SSL3", Qfalse);
|
652
|
+
#endif
|
653
|
+
|
654
|
+
#if defined(OPENSSL_NO_TLS1) || defined(OPENSSL_NO_TLS1_METHOD)
|
655
|
+
/* True if TLS1 is not available */
|
656
|
+
rb_define_const(mod, "OPENSSL_NO_TLS1", Qtrue);
|
657
|
+
#else
|
658
|
+
rb_define_const(mod, "OPENSSL_NO_TLS1", Qfalse);
|
659
|
+
#endif
|
660
|
+
|
661
|
+
#if defined(OPENSSL_NO_TLS1_1) || defined(OPENSSL_NO_TLS1_1_METHOD)
|
662
|
+
/* True if TLS1_1 is not available */
|
663
|
+
rb_define_const(mod, "OPENSSL_NO_TLS1_1", Qtrue);
|
664
|
+
#else
|
665
|
+
rb_define_const(mod, "OPENSSL_NO_TLS1_1", Qfalse);
|
446
666
|
#endif
|
447
667
|
|
448
668
|
rb_define_singleton_method(mod, "check", noop, 0);
|
@@ -463,13 +683,16 @@ void Init_mini_ssl(VALUE puma) {
|
|
463
683
|
rb_define_method(eng, "init?", engine_init, 0);
|
464
684
|
|
465
685
|
rb_define_method(eng, "peercert", engine_peercert, 0);
|
686
|
+
|
687
|
+
rb_define_method(eng, "ssl_vers_st", engine_ssl_vers_st, 0);
|
466
688
|
}
|
467
689
|
|
468
690
|
#else
|
469
691
|
|
692
|
+
NORETURN(VALUE raise_error(VALUE self));
|
693
|
+
|
470
694
|
VALUE raise_error(VALUE self) {
|
471
695
|
rb_raise(rb_eStandardError, "SSL not available in this build");
|
472
|
-
return Qnil;
|
473
696
|
}
|
474
697
|
|
475
698
|
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
|
+
}
|