puma 3.12.1 → 5.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of puma might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/History.md +1414 -448
- data/LICENSE +23 -20
- data/README.md +131 -60
- data/bin/puma-wild +3 -9
- data/docs/architecture.md +24 -19
- data/docs/compile_options.md +19 -0
- data/docs/deployment.md +38 -13
- 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/{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 +20 -10
- data/docs/rails_dev_mode.md +29 -0
- data/docs/restart.md +47 -22
- data/docs/signals.md +7 -6
- data/docs/stats.md +142 -0
- data/docs/systemd.md +48 -70
- data/ext/puma_http11/PumaHttp11Service.java +2 -2
- data/ext/puma_http11/ext_help.h +1 -1
- data/ext/puma_http11/extconf.rb +27 -0
- data/ext/puma_http11/http11_parser.c +84 -109
- 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 +3 -3
- data/ext/puma_http11/mini_ssl.c +254 -91
- 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 +89 -106
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +92 -22
- data/ext/puma_http11/puma_http11.c +34 -50
- data/lib/puma.rb +54 -0
- data/lib/puma/app/status.rb +68 -49
- data/lib/puma/binder.rb +191 -139
- data/lib/puma/cli.rb +15 -15
- data/lib/puma/client.rb +257 -228
- data/lib/puma/cluster.rb +221 -212
- data/lib/puma/cluster/worker.rb +183 -0
- data/lib/puma/cluster/worker_handle.rb +90 -0
- data/lib/puma/commonlogger.rb +2 -2
- data/lib/puma/configuration.rb +58 -51
- data/lib/puma/const.rb +39 -19
- data/lib/puma/control_cli.rb +109 -67
- data/lib/puma/detect.rb +24 -3
- data/lib/puma/dsl.rb +519 -121
- 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.rb +96 -0
- data/lib/puma/launcher.rb +178 -68
- data/lib/puma/minissl.rb +147 -48
- data/lib/puma/minissl/context_builder.rb +79 -0
- data/lib/puma/null_io.rb +13 -1
- data/lib/puma/plugin.rb +6 -12
- data/lib/puma/plugin/tmp_restart.rb +2 -0
- data/lib/puma/queue_close.rb +26 -0
- data/lib/puma/rack/builder.rb +2 -4
- 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 +467 -0
- data/lib/puma/runner.rb +31 -52
- data/lib/puma/server.rb +282 -680
- data/lib/puma/single.rb +11 -67
- data/lib/puma/state_file.rb +8 -3
- data/lib/puma/systemd.rb +46 -0
- data/lib/puma/thread_pool.rb +129 -81
- data/lib/puma/util.rb +13 -6
- data/lib/rack/handler/puma.rb +5 -6
- data/tools/Dockerfile +16 -0
- data/tools/trickletest.rb +0 -1
- metadata +42 -26
- 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,7 @@
|
|
1
1
|
package org.jruby.puma;
|
2
2
|
|
3
|
+
import org.jruby.Ruby;
|
4
|
+
import org.jruby.RubyHash;
|
3
5
|
import org.jruby.util.ByteList;
|
4
6
|
|
5
7
|
public class Http11Parser {
|
@@ -19,44 +21,35 @@ public class Http11Parser {
|
|
19
21
|
}
|
20
22
|
|
21
23
|
action start_value { parser.mark = fpc; }
|
22
|
-
action write_value {
|
23
|
-
|
24
|
-
parser.http_field.call(parser.data, parser.field_start, parser.field_len, parser.mark, fpc-parser.mark);
|
25
|
-
}
|
24
|
+
action write_value {
|
25
|
+
Http11.http_field(runtime, parser.data, parser.buffer, parser.field_start, parser.field_len, parser.mark, fpc-parser.mark);
|
26
26
|
}
|
27
|
-
action request_method {
|
28
|
-
|
29
|
-
parser.request_method.call(parser.data, parser.mark, fpc-parser.mark);
|
27
|
+
action request_method {
|
28
|
+
Http11.request_method(runtime, parser.data, parser.buffer, parser.mark, fpc-parser.mark);
|
30
29
|
}
|
31
|
-
action request_uri {
|
32
|
-
|
33
|
-
parser.request_uri.call(parser.data, parser.mark, fpc-parser.mark);
|
30
|
+
action request_uri {
|
31
|
+
Http11.request_uri(runtime, parser.data, parser.buffer, parser.mark, fpc-parser.mark);
|
34
32
|
}
|
35
|
-
action fragment {
|
36
|
-
|
37
|
-
parser.fragment.call(parser.data, parser.mark, fpc-parser.mark);
|
33
|
+
action fragment {
|
34
|
+
Http11.fragment(runtime, parser.data, parser.buffer, parser.mark, fpc-parser.mark);
|
38
35
|
}
|
39
36
|
|
40
37
|
action start_query {parser.query_start = fpc; }
|
41
|
-
action query_string {
|
42
|
-
|
43
|
-
parser.query_string.call(parser.data, parser.query_start, fpc-parser.query_start);
|
38
|
+
action query_string {
|
39
|
+
Http11.query_string(runtime, parser.data, parser.buffer, parser.query_start, fpc-parser.query_start);
|
44
40
|
}
|
45
41
|
|
46
|
-
action http_version {
|
47
|
-
|
48
|
-
parser.http_version.call(parser.data, parser.mark, fpc-parser.mark);
|
42
|
+
action http_version {
|
43
|
+
Http11.http_version(runtime, parser.data, parser.buffer, parser.mark, fpc-parser.mark);
|
49
44
|
}
|
50
45
|
|
51
46
|
action request_path {
|
52
|
-
|
53
|
-
parser.request_path.call(parser.data, parser.mark, fpc-parser.mark);
|
47
|
+
Http11.request_path(runtime, parser.data, parser.buffer, parser.mark, fpc-parser.mark);
|
54
48
|
}
|
55
49
|
|
56
50
|
action done {
|
57
|
-
parser.body_start = fpc + 1;
|
58
|
-
|
59
|
-
parser.header_done.call(parser.data, fpc + 1, pe - fpc - 1);
|
51
|
+
parser.body_start = fpc + 1;
|
52
|
+
http.header_done(runtime, parser.data, parser.buffer, fpc + 1, pe - fpc - 1);
|
60
53
|
fbreak;
|
61
54
|
}
|
62
55
|
|
@@ -65,14 +58,14 @@ public class Http11Parser {
|
|
65
58
|
}%%
|
66
59
|
|
67
60
|
/** Data **/
|
68
|
-
%% write data;
|
61
|
+
%% write data noentry;
|
69
62
|
|
70
63
|
public static interface ElementCB {
|
71
|
-
public void call(
|
64
|
+
public void call(Ruby runtime, RubyHash data, ByteList buffer, int at, int length);
|
72
65
|
}
|
73
66
|
|
74
67
|
public static interface FieldCB {
|
75
|
-
public void call(
|
68
|
+
public void call(Ruby runtime, RubyHash data, ByteList buffer, int field, int flen, int value, int vlen);
|
76
69
|
}
|
77
70
|
|
78
71
|
public static class HttpParser {
|
@@ -85,18 +78,9 @@ public class Http11Parser {
|
|
85
78
|
int field_len;
|
86
79
|
int query_start;
|
87
80
|
|
88
|
-
|
81
|
+
RubyHash data;
|
89
82
|
ByteList buffer;
|
90
83
|
|
91
|
-
public FieldCB http_field;
|
92
|
-
public ElementCB request_method;
|
93
|
-
public ElementCB request_uri;
|
94
|
-
public ElementCB fragment;
|
95
|
-
public ElementCB request_path;
|
96
|
-
public ElementCB query_string;
|
97
|
-
public ElementCB http_version;
|
98
|
-
public ElementCB header_done;
|
99
|
-
|
100
84
|
public void init() {
|
101
85
|
cs = 0;
|
102
86
|
|
@@ -113,7 +97,7 @@ public class Http11Parser {
|
|
113
97
|
|
114
98
|
public final HttpParser parser = new HttpParser();
|
115
99
|
|
116
|
-
public int execute(ByteList buffer, int off) {
|
100
|
+
public int execute(Ruby runtime, Http11 http, ByteList buffer, int off) {
|
117
101
|
int p, pe;
|
118
102
|
int cs = parser.cs;
|
119
103
|
int len = buffer.length();
|
@@ -12,12 +12,14 @@
|
|
12
12
|
|
13
13
|
/*
|
14
14
|
* capitalizes all lower-case ASCII characters,
|
15
|
-
* converts dashes to underscores.
|
15
|
+
* converts dashes to underscores, and underscores to commas.
|
16
16
|
*/
|
17
17
|
static void snake_upcase_char(char *c)
|
18
18
|
{
|
19
19
|
if (*c >= 'a' && *c <= 'z')
|
20
20
|
*c &= ~0x20;
|
21
|
+
else if (*c == '_')
|
22
|
+
*c = ',';
|
21
23
|
else if (*c == '-')
|
22
24
|
*c = '_';
|
23
25
|
}
|
@@ -79,7 +81,7 @@ static void snake_upcase_char(char *c)
|
|
79
81
|
}%%
|
80
82
|
|
81
83
|
/** Data **/
|
82
|
-
%% write data;
|
84
|
+
%% write data noentry;
|
83
85
|
|
84
86
|
int puma_parser_init(puma_parser *parser) {
|
85
87
|
int cs = 0;
|
@@ -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;
|
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,71 @@ 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);
|
58
|
-
|
59
|
-
conn->ssl = 0;
|
60
|
-
conn->ctx = 0;
|
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
|
+
};
|
61
51
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
DH *get_dh1024() {
|
66
|
-
/* `openssl dhparam 1024 -C`
|
52
|
+
DH *get_dh2048() {
|
53
|
+
/* `openssl dhparam -C 2048`
|
67
54
|
* -----BEGIN DH PARAMETERS-----
|
68
|
-
*
|
69
|
-
*
|
70
|
-
*
|
55
|
+
* MIIBCAKCAQEAjmh1uQHdTfxOyxEbKAV30fUfzqMDF/ChPzjfyzl2jcrqQMhrk76o
|
56
|
+
* 2NPNXqxHwsddMZ1RzvU8/jl+uhRuPWjXCFZbhET4N1vrviZM3VJhV8PPHuiVOACO
|
57
|
+
* y32jFd+Szx4bo2cXSK83hJ6jRd+0asP1awWjz9/06dFkrILCXMIfQLo0D8rqmppn
|
58
|
+
* EfDDAwuudCpM9kcDmBRAm9JsKbQ6gzZWjkc5+QWSaQofojIHbjvj3xzguaCJn+oQ
|
59
|
+
* vHWM+hsAnaOgEwCyeZ3xqs+/5lwSbkE/tqJW98cEZGygBUVo9jxZRZx6KOfjpdrb
|
60
|
+
* yenO9LJr/qtyrZB31WJbqxI0m0AKTAO8UwIBAg==
|
71
61
|
* -----END DH PARAMETERS-----
|
72
62
|
*/
|
73
|
-
static unsigned char
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
63
|
+
static unsigned char dh2048_p[] = {
|
64
|
+
0x8E, 0x68, 0x75, 0xB9, 0x01, 0xDD, 0x4D, 0xFC, 0x4E, 0xCB,
|
65
|
+
0x11, 0x1B, 0x28, 0x05, 0x77, 0xD1, 0xF5, 0x1F, 0xCE, 0xA3,
|
66
|
+
0x03, 0x17, 0xF0, 0xA1, 0x3F, 0x38, 0xDF, 0xCB, 0x39, 0x76,
|
67
|
+
0x8D, 0xCA, 0xEA, 0x40, 0xC8, 0x6B, 0x93, 0xBE, 0xA8, 0xD8,
|
68
|
+
0xD3, 0xCD, 0x5E, 0xAC, 0x47, 0xC2, 0xC7, 0x5D, 0x31, 0x9D,
|
69
|
+
0x51, 0xCE, 0xF5, 0x3C, 0xFE, 0x39, 0x7E, 0xBA, 0x14, 0x6E,
|
70
|
+
0x3D, 0x68, 0xD7, 0x08, 0x56, 0x5B, 0x84, 0x44, 0xF8, 0x37,
|
71
|
+
0x5B, 0xEB, 0xBE, 0x26, 0x4C, 0xDD, 0x52, 0x61, 0x57, 0xC3,
|
72
|
+
0xCF, 0x1E, 0xE8, 0x95, 0x38, 0x00, 0x8E, 0xCB, 0x7D, 0xA3,
|
73
|
+
0x15, 0xDF, 0x92, 0xCF, 0x1E, 0x1B, 0xA3, 0x67, 0x17, 0x48,
|
74
|
+
0xAF, 0x37, 0x84, 0x9E, 0xA3, 0x45, 0xDF, 0xB4, 0x6A, 0xC3,
|
75
|
+
0xF5, 0x6B, 0x05, 0xA3, 0xCF, 0xDF, 0xF4, 0xE9, 0xD1, 0x64,
|
76
|
+
0xAC, 0x82, 0xC2, 0x5C, 0xC2, 0x1F, 0x40, 0xBA, 0x34, 0x0F,
|
77
|
+
0xCA, 0xEA, 0x9A, 0x9A, 0x67, 0x11, 0xF0, 0xC3, 0x03, 0x0B,
|
78
|
+
0xAE, 0x74, 0x2A, 0x4C, 0xF6, 0x47, 0x03, 0x98, 0x14, 0x40,
|
79
|
+
0x9B, 0xD2, 0x6C, 0x29, 0xB4, 0x3A, 0x83, 0x36, 0x56, 0x8E,
|
80
|
+
0x47, 0x39, 0xF9, 0x05, 0x92, 0x69, 0x0A, 0x1F, 0xA2, 0x32,
|
81
|
+
0x07, 0x6E, 0x3B, 0xE3, 0xDF, 0x1C, 0xE0, 0xB9, 0xA0, 0x89,
|
82
|
+
0x9F, 0xEA, 0x10, 0xBC, 0x75, 0x8C, 0xFA, 0x1B, 0x00, 0x9D,
|
83
|
+
0xA3, 0xA0, 0x13, 0x00, 0xB2, 0x79, 0x9D, 0xF1, 0xAA, 0xCF,
|
84
|
+
0xBF, 0xE6, 0x5C, 0x12, 0x6E, 0x41, 0x3F, 0xB6, 0xA2, 0x56,
|
85
|
+
0xF7, 0xC7, 0x04, 0x64, 0x6C, 0xA0, 0x05, 0x45, 0x68, 0xF6,
|
86
|
+
0x3C, 0x59, 0x45, 0x9C, 0x7A, 0x28, 0xE7, 0xE3, 0xA5, 0xDA,
|
87
|
+
0xDB, 0xC9, 0xE9, 0xCE, 0xF4, 0xB2, 0x6B, 0xFE, 0xAB, 0x72,
|
88
|
+
0xAD, 0x90, 0x77, 0xD5, 0x62, 0x5B, 0xAB, 0x12, 0x34, 0x9B,
|
89
|
+
0x40, 0x0A, 0x4C, 0x03, 0xBC, 0x53
|
85
90
|
};
|
86
|
-
static unsigned char
|
91
|
+
static unsigned char dh2048_g[] = { 0x02 };
|
87
92
|
|
88
93
|
DH *dh;
|
94
|
+
#if !(OPENSSL_VERSION_NUMBER < 0x10100005L || defined(LIBRESSL_VERSION_NUMBER))
|
95
|
+
BIGNUM *p, *g;
|
96
|
+
#endif
|
97
|
+
|
89
98
|
dh = DH_new();
|
90
99
|
|
91
100
|
#if OPENSSL_VERSION_NUMBER < 0x10100005L || defined(LIBRESSL_VERSION_NUMBER)
|
92
|
-
dh->p = BN_bin2bn(
|
93
|
-
dh->g = BN_bin2bn(
|
101
|
+
dh->p = BN_bin2bn(dh2048_p, sizeof(dh2048_p), NULL);
|
102
|
+
dh->g = BN_bin2bn(dh2048_g, sizeof(dh2048_g), NULL);
|
94
103
|
|
95
104
|
if ((dh->p == NULL) || (dh->g == NULL)) {
|
96
105
|
DH_free(dh);
|
97
106
|
return NULL;
|
98
107
|
}
|
99
108
|
#else
|
100
|
-
|
101
|
-
|
102
|
-
g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
|
109
|
+
p = BN_bin2bn(dh2048_p, sizeof(dh2048_p), NULL);
|
110
|
+
g = BN_bin2bn(dh2048_g, sizeof(dh2048_g), NULL);
|
103
111
|
|
104
112
|
if (p == NULL || g == NULL || !DH_set0_pqg(dh, p, NULL, g)) {
|
105
113
|
DH_free(dh);
|
@@ -112,6 +120,37 @@ DH *get_dh1024() {
|
|
112
120
|
return dh;
|
113
121
|
}
|
114
122
|
|
123
|
+
static void
|
124
|
+
sslctx_free(void *ptr) {
|
125
|
+
SSL_CTX *ctx = ptr;
|
126
|
+
SSL_CTX_free(ctx);
|
127
|
+
}
|
128
|
+
|
129
|
+
static const rb_data_type_t sslctx_type = {
|
130
|
+
"MiniSSL/SSLContext",
|
131
|
+
{
|
132
|
+
0, sslctx_free,
|
133
|
+
},
|
134
|
+
0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
|
135
|
+
};
|
136
|
+
|
137
|
+
ms_conn* engine_alloc(VALUE klass, VALUE* obj) {
|
138
|
+
ms_conn* conn;
|
139
|
+
|
140
|
+
*obj = TypedData_Make_Struct(klass, ms_conn, &engine_data_type, conn);
|
141
|
+
|
142
|
+
conn->read = BIO_new(BIO_s_mem());
|
143
|
+
BIO_set_nbio(conn->read, 1);
|
144
|
+
|
145
|
+
conn->write = BIO_new(BIO_s_mem());
|
146
|
+
BIO_set_nbio(conn->write, 1);
|
147
|
+
|
148
|
+
conn->ssl = 0;
|
149
|
+
conn->ctx = 0;
|
150
|
+
|
151
|
+
return conn;
|
152
|
+
}
|
153
|
+
|
115
154
|
static int engine_verify_callback(int preverify_ok, X509_STORE_CTX* ctx) {
|
116
155
|
X509* err_cert;
|
117
156
|
SSL* ssl;
|
@@ -138,44 +177,108 @@ static int engine_verify_callback(int preverify_ok, X509_STORE_CTX* ctx) {
|
|
138
177
|
return preverify_ok;
|
139
178
|
}
|
140
179
|
|
141
|
-
|
142
|
-
|
180
|
+
static VALUE
|
181
|
+
sslctx_alloc(VALUE klass) {
|
182
|
+
SSL_CTX *ctx;
|
183
|
+
long mode = 0 |
|
184
|
+
SSL_MODE_ENABLE_PARTIAL_WRITE |
|
185
|
+
SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
|
186
|
+
SSL_MODE_RELEASE_BUFFERS;
|
187
|
+
|
188
|
+
#ifdef HAVE_TLS_SERVER_METHOD
|
189
|
+
ctx = SSL_CTX_new(TLS_method());
|
190
|
+
// printf("\nctx using TLS_method security_level %d\n", SSL_CTX_get_security_level(ctx));
|
191
|
+
#else
|
192
|
+
ctx = SSL_CTX_new(SSLv23_method());
|
193
|
+
#endif
|
194
|
+
if (!ctx) {
|
195
|
+
rb_raise(eError, "SSL_CTX_new");
|
196
|
+
}
|
197
|
+
SSL_CTX_set_mode(ctx, mode);
|
198
|
+
|
199
|
+
return TypedData_Wrap_Struct(klass, &sslctx_type, ctx);
|
200
|
+
}
|
201
|
+
|
202
|
+
VALUE
|
203
|
+
sslctx_initialize(VALUE self, VALUE mini_ssl_ctx) {
|
143
204
|
SSL_CTX* ctx;
|
144
|
-
SSL* ssl;
|
145
205
|
|
146
|
-
|
206
|
+
#ifdef HAVE_SSL_CTX_SET_MIN_PROTO_VERSION
|
207
|
+
int min;
|
208
|
+
#endif
|
209
|
+
int ssl_options;
|
210
|
+
VALUE key, cert, ca, verify_mode, ssl_cipher_filter, no_tlsv1, no_tlsv1_1,
|
211
|
+
verification_flags;
|
212
|
+
DH *dh;
|
213
|
+
|
214
|
+
#if OPENSSL_VERSION_NUMBER < 0x10002000L
|
215
|
+
EC_KEY *ecdh;
|
216
|
+
#endif
|
147
217
|
|
148
|
-
|
149
|
-
VALUE key = rb_funcall(mini_ssl_ctx, sym_key, 0);
|
218
|
+
TypedData_Get_Struct(self, SSL_CTX, &sslctx_type, ctx);
|
150
219
|
|
220
|
+
key = rb_funcall(mini_ssl_ctx, rb_intern_const("key"), 0);
|
151
221
|
StringValue(key);
|
152
222
|
|
153
|
-
|
154
|
-
VALUE cert = rb_funcall(mini_ssl_ctx, sym_cert, 0);
|
155
|
-
|
223
|
+
cert = rb_funcall(mini_ssl_ctx, rb_intern_const("cert"), 0);
|
156
224
|
StringValue(cert);
|
157
225
|
|
158
|
-
|
159
|
-
VALUE ca = rb_funcall(mini_ssl_ctx, sym_ca, 0);
|
226
|
+
ca = rb_funcall(mini_ssl_ctx, rb_intern_const("ca"), 0);
|
160
227
|
|
161
|
-
|
162
|
-
VALUE verify_mode = rb_funcall(mini_ssl_ctx, sym_verify_mode, 0);
|
228
|
+
verify_mode = rb_funcall(mini_ssl_ctx, rb_intern_const("verify_mode"), 0);
|
163
229
|
|
164
|
-
|
165
|
-
VALUE ssl_cipher_filter = rb_funcall(mini_ssl_ctx, sym_ssl_cipher_filter, 0);
|
230
|
+
ssl_cipher_filter = rb_funcall(mini_ssl_ctx, rb_intern_const("ssl_cipher_filter"), 0);
|
166
231
|
|
167
|
-
|
168
|
-
|
232
|
+
no_tlsv1 = rb_funcall(mini_ssl_ctx, rb_intern_const("no_tlsv1"), 0);
|
233
|
+
|
234
|
+
no_tlsv1_1 = rb_funcall(mini_ssl_ctx, rb_intern_const("no_tlsv1_1"), 0);
|
169
235
|
|
170
236
|
SSL_CTX_use_certificate_chain_file(ctx, RSTRING_PTR(cert));
|
171
237
|
SSL_CTX_use_PrivateKey_file(ctx, RSTRING_PTR(key), SSL_FILETYPE_PEM);
|
172
238
|
|
239
|
+
verification_flags = rb_funcall(mini_ssl_ctx, rb_intern_const("verification_flags"), 0);
|
240
|
+
|
241
|
+
if (!NIL_P(verification_flags)) {
|
242
|
+
X509_VERIFY_PARAM *param = SSL_CTX_get0_param(ctx);
|
243
|
+
X509_VERIFY_PARAM_set_flags(param, NUM2INT(verification_flags));
|
244
|
+
SSL_CTX_set1_param(ctx, param);
|
245
|
+
}
|
246
|
+
|
173
247
|
if (!NIL_P(ca)) {
|
174
248
|
StringValue(ca);
|
175
249
|
SSL_CTX_load_verify_locations(ctx, RSTRING_PTR(ca), NULL);
|
176
250
|
}
|
177
251
|
|
178
|
-
|
252
|
+
ssl_options = SSL_OP_CIPHER_SERVER_PREFERENCE | SSL_OP_SINGLE_ECDH_USE | SSL_OP_NO_COMPRESSION;
|
253
|
+
|
254
|
+
#ifdef HAVE_SSL_CTX_SET_MIN_PROTO_VERSION
|
255
|
+
if (RTEST(no_tlsv1_1)) {
|
256
|
+
min = TLS1_2_VERSION;
|
257
|
+
}
|
258
|
+
else if (RTEST(no_tlsv1)) {
|
259
|
+
min = TLS1_1_VERSION;
|
260
|
+
}
|
261
|
+
else {
|
262
|
+
min = TLS1_VERSION;
|
263
|
+
}
|
264
|
+
|
265
|
+
SSL_CTX_set_min_proto_version(ctx, min);
|
266
|
+
|
267
|
+
SSL_CTX_set_options(ctx, ssl_options);
|
268
|
+
|
269
|
+
#else
|
270
|
+
/* As of 1.0.2f, SSL_OP_SINGLE_DH_USE key use is always on */
|
271
|
+
ssl_options |= SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_SINGLE_DH_USE;
|
272
|
+
|
273
|
+
if (RTEST(no_tlsv1)) {
|
274
|
+
ssl_options |= SSL_OP_NO_TLSv1;
|
275
|
+
}
|
276
|
+
if(RTEST(no_tlsv1_1)) {
|
277
|
+
ssl_options |= SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1;
|
278
|
+
}
|
279
|
+
SSL_CTX_set_options(ctx, ssl_options);
|
280
|
+
#endif
|
281
|
+
|
179
282
|
SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
|
180
283
|
|
181
284
|
if (!NIL_P(ssl_cipher_filter)) {
|
@@ -186,29 +289,45 @@ VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) {
|
|
186
289
|
SSL_CTX_set_cipher_list(ctx, "HIGH:!aNULL@STRENGTH");
|
187
290
|
}
|
188
291
|
|
189
|
-
|
292
|
+
dh = get_dh2048();
|
190
293
|
SSL_CTX_set_tmp_dh(ctx, dh);
|
191
294
|
|
192
|
-
#
|
193
|
-
|
295
|
+
#if OPENSSL_VERSION_NUMBER < 0x10002000L
|
296
|
+
// Remove this case if OpenSSL 1.0.1 (now EOL) support is no
|
297
|
+
// longer needed.
|
298
|
+
ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
|
194
299
|
if (ecdh) {
|
195
300
|
SSL_CTX_set_tmp_ecdh(ctx, ecdh);
|
196
301
|
EC_KEY_free(ecdh);
|
197
302
|
}
|
303
|
+
#elif OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
|
304
|
+
SSL_CTX_set_ecdh_auto(ctx, 1);
|
198
305
|
#endif
|
199
306
|
|
200
|
-
ssl = SSL_new(ctx);
|
201
|
-
conn->ssl = ssl;
|
202
|
-
SSL_set_app_data(ssl, NULL);
|
203
|
-
|
204
307
|
if (NIL_P(verify_mode)) {
|
205
|
-
/*
|
308
|
+
/* SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); */
|
206
309
|
} else {
|
207
|
-
|
310
|
+
SSL_CTX_set_verify(ctx, NUM2INT(verify_mode), engine_verify_callback);
|
208
311
|
}
|
312
|
+
// printf("\ninitialize end security_level %d\n", SSL_CTX_get_security_level(ctx));
|
313
|
+
rb_obj_freeze(self);
|
314
|
+
return self;
|
315
|
+
}
|
209
316
|
|
210
|
-
|
317
|
+
VALUE engine_init_server(VALUE self, VALUE sslctx) {
|
318
|
+
ms_conn* conn;
|
319
|
+
VALUE obj;
|
320
|
+
SSL_CTX* ctx;
|
321
|
+
SSL* ssl;
|
211
322
|
|
323
|
+
conn = engine_alloc(self, &obj);
|
324
|
+
|
325
|
+
TypedData_Get_Struct(sslctx, SSL_CTX, &sslctx_type, ctx);
|
326
|
+
|
327
|
+
ssl = SSL_new(ctx);
|
328
|
+
conn->ssl = ssl;
|
329
|
+
SSL_set_app_data(ssl, NULL);
|
330
|
+
SSL_set_bio(ssl, conn->read, conn->write);
|
212
331
|
SSL_set_accept_state(ssl);
|
213
332
|
return obj;
|
214
333
|
}
|
@@ -216,8 +335,11 @@ VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) {
|
|
216
335
|
VALUE engine_init_client(VALUE klass) {
|
217
336
|
VALUE obj;
|
218
337
|
ms_conn* conn = engine_alloc(klass, &obj);
|
219
|
-
|
338
|
+
#ifdef HAVE_DTLS_METHOD
|
339
|
+
conn->ctx = SSL_CTX_new(DTLS_method());
|
340
|
+
#else
|
220
341
|
conn->ctx = SSL_CTX_new(DTLSv1_method());
|
342
|
+
#endif
|
221
343
|
conn->ssl = SSL_new(conn->ctx);
|
222
344
|
SSL_set_app_data(conn->ssl, NULL);
|
223
345
|
SSL_set_verify(conn->ssl, SSL_VERIFY_NONE, NULL);
|
@@ -232,7 +354,7 @@ VALUE engine_inject(VALUE self, VALUE str) {
|
|
232
354
|
ms_conn* conn;
|
233
355
|
long used;
|
234
356
|
|
235
|
-
|
357
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
236
358
|
|
237
359
|
StringValue(str);
|
238
360
|
|
@@ -245,13 +367,14 @@ VALUE engine_inject(VALUE self, VALUE str) {
|
|
245
367
|
return INT2FIX(used);
|
246
368
|
}
|
247
369
|
|
248
|
-
|
370
|
+
NORETURN(void raise_error(SSL* ssl, int result));
|
249
371
|
|
250
372
|
void raise_error(SSL* ssl, int result) {
|
251
373
|
char buf[512];
|
252
374
|
char msg[512];
|
253
375
|
const char* err_str;
|
254
376
|
int err = errno;
|
377
|
+
int mask = 4095;
|
255
378
|
int ssl_err = SSL_get_error(ssl, result);
|
256
379
|
int verify_err = (int) SSL_get_verify_result(ssl);
|
257
380
|
|
@@ -268,8 +391,7 @@ void raise_error(SSL* ssl, int result) {
|
|
268
391
|
} else {
|
269
392
|
err = (int) ERR_get_error();
|
270
393
|
ERR_error_string_n(err, buf, sizeof(buf));
|
271
|
-
snprintf(msg, sizeof(msg), "OpenSSL error: %s - %d", buf, err);
|
272
|
-
|
394
|
+
snprintf(msg, sizeof(msg), "OpenSSL error: %s - %d", buf, err & mask);
|
273
395
|
}
|
274
396
|
} else {
|
275
397
|
snprintf(msg, sizeof(msg), "Unknown OpenSSL error: %d", ssl_err);
|
@@ -284,7 +406,7 @@ VALUE engine_read(VALUE self) {
|
|
284
406
|
char buf[512];
|
285
407
|
int bytes, error;
|
286
408
|
|
287
|
-
|
409
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
288
410
|
|
289
411
|
ERR_clear_error();
|
290
412
|
|
@@ -311,7 +433,7 @@ VALUE engine_write(VALUE self, VALUE str) {
|
|
311
433
|
ms_conn* conn;
|
312
434
|
int bytes;
|
313
435
|
|
314
|
-
|
436
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
315
437
|
|
316
438
|
StringValue(str);
|
317
439
|
|
@@ -333,9 +455,11 @@ VALUE engine_extract(VALUE self) {
|
|
333
455
|
ms_conn* conn;
|
334
456
|
int bytes;
|
335
457
|
size_t pending;
|
336
|
-
|
458
|
+
// https://www.openssl.org/docs/manmaster/man3/BIO_f_buffer.html
|
459
|
+
// crypto/bio/bf_buff.c DEFAULT_BUFFER_SIZE
|
460
|
+
char buf[4096];
|
337
461
|
|
338
|
-
|
462
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
339
463
|
|
340
464
|
pending = BIO_pending(conn->write);
|
341
465
|
if(pending > 0) {
|
@@ -354,7 +478,7 @@ VALUE engine_shutdown(VALUE self) {
|
|
354
478
|
ms_conn* conn;
|
355
479
|
int ok;
|
356
480
|
|
357
|
-
|
481
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
358
482
|
|
359
483
|
ERR_clear_error();
|
360
484
|
|
@@ -369,7 +493,7 @@ VALUE engine_shutdown(VALUE self) {
|
|
369
493
|
VALUE engine_init(VALUE self) {
|
370
494
|
ms_conn* conn;
|
371
495
|
|
372
|
-
|
496
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
373
497
|
|
374
498
|
return SSL_in_init(conn->ssl) ? Qtrue : Qfalse;
|
375
499
|
}
|
@@ -382,7 +506,7 @@ VALUE engine_peercert(VALUE self) {
|
|
382
506
|
ms_cert_buf* cert_buf = NULL;
|
383
507
|
VALUE rb_cert_buf;
|
384
508
|
|
385
|
-
|
509
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
386
510
|
|
387
511
|
cert = SSL_get_peer_certificate(conn->ssl);
|
388
512
|
if(!cert) {
|
@@ -413,12 +537,22 @@ VALUE engine_peercert(VALUE self) {
|
|
413
537
|
return rb_cert_buf;
|
414
538
|
}
|
415
539
|
|
540
|
+
/* @see Puma::MiniSSL::Socket#ssl_version_state
|
541
|
+
* @version 5.0.0
|
542
|
+
*/
|
543
|
+
static VALUE
|
544
|
+
engine_ssl_vers_st(VALUE self) {
|
545
|
+
ms_conn* conn;
|
546
|
+
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
|
547
|
+
return rb_ary_new3(2, rb_str_new2(SSL_get_version(conn->ssl)), rb_str_new2(SSL_state_string(conn->ssl)));
|
548
|
+
}
|
549
|
+
|
416
550
|
VALUE noop(VALUE self) {
|
417
551
|
return Qnil;
|
418
552
|
}
|
419
553
|
|
420
554
|
void Init_mini_ssl(VALUE puma) {
|
421
|
-
VALUE mod, eng;
|
555
|
+
VALUE mod, eng, sslctx;
|
422
556
|
|
423
557
|
/* Fake operation for documentation (RDoc, YARD) */
|
424
558
|
#if 0 == 1
|
@@ -432,17 +566,43 @@ void Init_mini_ssl(VALUE puma) {
|
|
432
566
|
|
433
567
|
mod = rb_define_module_under(puma, "MiniSSL");
|
434
568
|
eng = rb_define_class_under(mod, "Engine", rb_cObject);
|
569
|
+
sslctx = rb_define_class_under(mod, "SSLContext", rb_cObject);
|
570
|
+
rb_define_alloc_func(sslctx, sslctx_alloc);
|
571
|
+
rb_define_method(sslctx, "initialize", sslctx_initialize, 1);
|
572
|
+
rb_undef_method(sslctx, "initialize_copy");
|
573
|
+
|
435
574
|
|
436
575
|
// OpenSSL Build / Runtime/Load versions
|
437
576
|
|
438
577
|
/* Version of OpenSSL that Puma was compiled with */
|
439
|
-
|
578
|
+
rb_define_const(mod, "OPENSSL_VERSION", rb_str_new2(OPENSSL_VERSION_TEXT));
|
440
579
|
|
441
580
|
#if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000
|
442
|
-
|
443
|
-
|
581
|
+
/* Version of OpenSSL that Puma loaded with */
|
582
|
+
rb_define_const(mod, "OPENSSL_LIBRARY_VERSION", rb_str_new2(OpenSSL_version(OPENSSL_VERSION)));
|
583
|
+
#else
|
584
|
+
rb_define_const(mod, "OPENSSL_LIBRARY_VERSION", rb_str_new2(SSLeay_version(SSLEAY_VERSION)));
|
585
|
+
#endif
|
586
|
+
|
587
|
+
#if defined(OPENSSL_NO_SSL3) || defined(OPENSSL_NO_SSL3_METHOD)
|
588
|
+
/* True if SSL3 is not available */
|
589
|
+
rb_define_const(mod, "OPENSSL_NO_SSL3", Qtrue);
|
590
|
+
#else
|
591
|
+
rb_define_const(mod, "OPENSSL_NO_SSL3", Qfalse);
|
592
|
+
#endif
|
593
|
+
|
594
|
+
#if defined(OPENSSL_NO_TLS1) || defined(OPENSSL_NO_TLS1_METHOD)
|
595
|
+
/* True if TLS1 is not available */
|
596
|
+
rb_define_const(mod, "OPENSSL_NO_TLS1", Qtrue);
|
444
597
|
#else
|
445
|
-
|
598
|
+
rb_define_const(mod, "OPENSSL_NO_TLS1", Qfalse);
|
599
|
+
#endif
|
600
|
+
|
601
|
+
#if defined(OPENSSL_NO_TLS1_1) || defined(OPENSSL_NO_TLS1_1_METHOD)
|
602
|
+
/* True if TLS1_1 is not available */
|
603
|
+
rb_define_const(mod, "OPENSSL_NO_TLS1_1", Qtrue);
|
604
|
+
#else
|
605
|
+
rb_define_const(mod, "OPENSSL_NO_TLS1_1", Qfalse);
|
446
606
|
#endif
|
447
607
|
|
448
608
|
rb_define_singleton_method(mod, "check", noop, 0);
|
@@ -463,13 +623,16 @@ void Init_mini_ssl(VALUE puma) {
|
|
463
623
|
rb_define_method(eng, "init?", engine_init, 0);
|
464
624
|
|
465
625
|
rb_define_method(eng, "peercert", engine_peercert, 0);
|
626
|
+
|
627
|
+
rb_define_method(eng, "ssl_vers_st", engine_ssl_vers_st, 0);
|
466
628
|
}
|
467
629
|
|
468
630
|
#else
|
469
631
|
|
632
|
+
NORETURN(VALUE raise_error(VALUE self));
|
633
|
+
|
470
634
|
VALUE raise_error(VALUE self) {
|
471
635
|
rb_raise(rb_eStandardError, "SSL not available in this build");
|
472
|
-
return Qnil;
|
473
636
|
}
|
474
637
|
|
475
638
|
void Init_mini_ssl(VALUE puma) {
|