puma 2.0.0.b5 → 5.0.0.beta1
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 +7 -0
- data/History.md +1598 -0
- data/LICENSE +23 -20
- data/README.md +222 -62
- data/bin/puma-wild +31 -0
- data/bin/pumactl +1 -1
- data/docs/architecture.md +37 -0
- data/docs/deployment.md +113 -0
- data/docs/fork_worker.md +31 -0
- data/docs/images/puma-connection-flow-no-reactor.png +0 -0
- data/docs/images/puma-connection-flow.png +0 -0
- data/docs/images/puma-general-arch.png +0 -0
- data/docs/jungle/README.md +13 -0
- data/docs/jungle/rc.d/README.md +74 -0
- data/docs/jungle/rc.d/puma +61 -0
- data/docs/jungle/rc.d/puma.conf +10 -0
- data/docs/jungle/upstart/README.md +61 -0
- data/docs/jungle/upstart/puma-manager.conf +31 -0
- data/docs/jungle/upstart/puma.conf +69 -0
- data/docs/nginx.md +5 -10
- data/docs/plugins.md +38 -0
- data/docs/restart.md +41 -0
- data/docs/signals.md +97 -0
- data/docs/systemd.md +228 -0
- data/ext/puma_http11/PumaHttp11Service.java +2 -2
- data/ext/puma_http11/extconf.rb +23 -2
- data/ext/puma_http11/http11_parser.c +301 -482
- data/ext/puma_http11/http11_parser.h +13 -11
- data/ext/puma_http11/http11_parser.java.rl +26 -42
- data/ext/puma_http11/http11_parser.rl +22 -21
- data/ext/puma_http11/http11_parser_common.rl +5 -5
- data/ext/puma_http11/mini_ssl.c +377 -18
- data/ext/puma_http11/org/jruby/puma/Http11.java +108 -107
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +137 -170
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +265 -191
- data/ext/puma_http11/puma_http11.c +57 -81
- data/lib/puma.rb +25 -4
- data/lib/puma/accept_nonblock.rb +7 -1
- data/lib/puma/app/status.rb +61 -24
- data/lib/puma/binder.rb +212 -78
- data/lib/puma/cli.rb +149 -644
- data/lib/puma/client.rb +316 -65
- data/lib/puma/cluster.rb +659 -0
- data/lib/puma/commonlogger.rb +108 -0
- data/lib/puma/configuration.rb +279 -180
- data/lib/puma/const.rb +126 -39
- data/lib/puma/control_cli.rb +183 -96
- data/lib/puma/detect.rb +20 -1
- data/lib/puma/dsl.rb +776 -0
- data/lib/puma/events.rb +91 -23
- data/lib/puma/io_buffer.rb +9 -5
- data/lib/puma/jruby_restart.rb +9 -5
- data/lib/puma/launcher.rb +487 -0
- data/lib/puma/minissl.rb +239 -93
- data/lib/puma/minissl/context_builder.rb +76 -0
- data/lib/puma/null_io.rb +22 -12
- data/lib/puma/plugin.rb +111 -0
- data/lib/puma/plugin/tmp_restart.rb +36 -0
- data/lib/puma/rack/builder.rb +297 -0
- data/lib/puma/rack/urlmap.rb +93 -0
- data/lib/puma/rack_default.rb +9 -0
- data/lib/puma/reactor.rb +290 -43
- data/lib/puma/runner.rb +163 -0
- data/lib/puma/server.rb +493 -126
- data/lib/puma/single.rb +66 -0
- data/lib/puma/state_file.rb +34 -0
- data/lib/puma/thread_pool.rb +228 -47
- data/lib/puma/util.rb +115 -0
- data/lib/rack/handler/puma.rb +78 -31
- data/tools/Dockerfile +16 -0
- data/tools/trickletest.rb +44 -0
- metadata +60 -155
- data/COPYING +0 -55
- data/Gemfile +0 -8
- data/History.txt +0 -196
- data/Manifest.txt +0 -56
- data/Rakefile +0 -121
- data/TODO +0 -5
- data/docs/config.md +0 -0
- data/ext/puma_http11/io_buffer.c +0 -154
- data/lib/puma/capistrano.rb +0 -26
- data/lib/puma/compat.rb +0 -11
- data/lib/puma/daemon_ext.rb +0 -20
- data/lib/puma/delegation.rb +0 -11
- data/lib/puma/java_io_buffer.rb +0 -45
- data/lib/puma/rack_patch.rb +0 -25
- data/puma.gemspec +0 -45
- data/test/test_app_status.rb +0 -88
- data/test/test_cli.rb +0 -171
- data/test/test_config.rb +0 -16
- data/test/test_http10.rb +0 -27
- data/test/test_http11.rb +0 -126
- data/test/test_integration.rb +0 -150
- data/test/test_iobuffer.rb +0 -38
- data/test/test_minissl.rb +0 -22
- data/test/test_null_io.rb +0 -31
- data/test/test_persistent.rb +0 -238
- data/test/test_puma_server.rb +0 -128
- data/test/test_rack_handler.rb +0 -10
- data/test/test_rack_server.rb +0 -141
- data/test/test_thread_pool.rb +0 -146
- data/test/test_unix_socket.rb +0 -39
- data/test/test_ws.rb +0 -89
- data/tools/jungle/README.md +0 -54
- data/tools/jungle/puma +0 -332
- data/tools/jungle/run-puma +0 -3
@@ -1,11 +1,13 @@
|
|
1
1
|
/**
|
2
2
|
* Copyright (c) 2005 Zed A. Shaw
|
3
3
|
* You can redistribute it and/or modify it under the same terms as Ruby.
|
4
|
+
* License 3-clause BSD
|
4
5
|
*/
|
5
6
|
|
6
7
|
#ifndef http11_parser_h
|
7
8
|
#define http11_parser_h
|
8
9
|
|
10
|
+
#define RSTRING_NOT_MODIFIED 1
|
9
11
|
#include "ruby.h"
|
10
12
|
|
11
13
|
#include <sys/types.h>
|
@@ -16,16 +18,16 @@
|
|
16
18
|
|
17
19
|
#define BUFFER_LEN 1024
|
18
20
|
|
19
|
-
struct
|
21
|
+
struct puma_parser;
|
20
22
|
|
21
|
-
typedef void (*element_cb)(struct
|
23
|
+
typedef void (*element_cb)(struct puma_parser* hp,
|
22
24
|
const char *at, size_t length);
|
23
25
|
|
24
|
-
typedef void (*field_cb)(struct
|
26
|
+
typedef void (*field_cb)(struct puma_parser* hp,
|
25
27
|
const char *field, size_t flen,
|
26
28
|
const char *value, size_t vlen);
|
27
29
|
|
28
|
-
typedef struct
|
30
|
+
typedef struct puma_parser {
|
29
31
|
int cs;
|
30
32
|
size_t body_start;
|
31
33
|
int content_len;
|
@@ -49,15 +51,15 @@ typedef struct http_parser {
|
|
49
51
|
|
50
52
|
char buf[BUFFER_LEN];
|
51
53
|
|
52
|
-
}
|
54
|
+
} puma_parser;
|
53
55
|
|
54
|
-
int
|
55
|
-
int
|
56
|
-
size_t
|
56
|
+
int puma_parser_init(puma_parser *parser);
|
57
|
+
int puma_parser_finish(puma_parser *parser);
|
58
|
+
size_t puma_parser_execute(puma_parser *parser, const char *data,
|
57
59
|
size_t len, size_t off);
|
58
|
-
int
|
59
|
-
int
|
60
|
+
int puma_parser_has_error(puma_parser *parser);
|
61
|
+
int puma_parser_is_finished(puma_parser *parser);
|
60
62
|
|
61
|
-
#define
|
63
|
+
#define puma_parser_nread(parser) (parser)->nread
|
62
64
|
|
63
65
|
#endif
|
@@ -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 {
|
@@ -7,8 +9,8 @@ public class Http11Parser {
|
|
7
9
|
/** Machine **/
|
8
10
|
|
9
11
|
%%{
|
10
|
-
|
11
|
-
machine
|
12
|
+
|
13
|
+
machine puma_parser;
|
12
14
|
|
13
15
|
action mark {parser.mark = fpc; }
|
14
16
|
|
@@ -19,48 +21,39 @@ 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
|
|
63
|
-
include
|
56
|
+
include puma_parser_common "http11_parser_common.rl";
|
64
57
|
|
65
58
|
}%%
|
66
59
|
|
@@ -68,11 +61,11 @@ public class Http11Parser {
|
|
68
61
|
%% write data;
|
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();
|
@@ -152,10 +136,10 @@ public class Http11Parser {
|
|
152
136
|
}
|
153
137
|
|
154
138
|
public boolean has_error() {
|
155
|
-
return parser.cs ==
|
139
|
+
return parser.cs == puma_parser_error;
|
156
140
|
}
|
157
141
|
|
158
142
|
public boolean is_finished() {
|
159
|
-
return parser.cs ==
|
143
|
+
return parser.cs == puma_parser_first_final;
|
160
144
|
}
|
161
145
|
}
|
@@ -1,6 +1,7 @@
|
|
1
1
|
/**
|
2
2
|
* Copyright (c) 2005 Zed A. Shaw
|
3
3
|
* You can redistribute it and/or modify it under the same terms as Ruby.
|
4
|
+
* License 3-clause BSD
|
4
5
|
*/
|
5
6
|
#include "http11_parser.h"
|
6
7
|
#include <stdio.h>
|
@@ -28,15 +29,15 @@ static void snake_upcase_char(char *c)
|
|
28
29
|
/** Machine **/
|
29
30
|
|
30
31
|
%%{
|
31
|
-
|
32
|
-
machine
|
32
|
+
|
33
|
+
machine puma_parser;
|
33
34
|
|
34
35
|
action mark { MARK(mark, fpc); }
|
35
36
|
|
36
37
|
|
37
38
|
action start_field { MARK(field_start, fpc); }
|
38
39
|
action snake_upcase_field { snake_upcase_char((char *)fpc); }
|
39
|
-
action write_field {
|
40
|
+
action write_field {
|
40
41
|
parser->field_len = LEN(field_start, fpc);
|
41
42
|
}
|
42
43
|
|
@@ -44,10 +45,10 @@ static void snake_upcase_char(char *c)
|
|
44
45
|
action write_value {
|
45
46
|
parser->http_field(parser, PTR_TO(field_start), parser->field_len, PTR_TO(mark), LEN(mark, fpc));
|
46
47
|
}
|
47
|
-
action request_method {
|
48
|
+
action request_method {
|
48
49
|
parser->request_method(parser, PTR_TO(mark), LEN(mark, fpc));
|
49
50
|
}
|
50
|
-
action request_uri {
|
51
|
+
action request_uri {
|
51
52
|
parser->request_uri(parser, PTR_TO(mark), LEN(mark, fpc));
|
52
53
|
}
|
53
54
|
action fragment {
|
@@ -55,11 +56,11 @@ static void snake_upcase_char(char *c)
|
|
55
56
|
}
|
56
57
|
|
57
58
|
action start_query { MARK(query_start, fpc); }
|
58
|
-
action query_string {
|
59
|
+
action query_string {
|
59
60
|
parser->query_string(parser, PTR_TO(query_start), LEN(query_start, fpc));
|
60
61
|
}
|
61
62
|
|
62
|
-
action http_version {
|
63
|
+
action http_version {
|
63
64
|
parser->http_version(parser, PTR_TO(mark), LEN(mark, fpc));
|
64
65
|
}
|
65
66
|
|
@@ -67,20 +68,20 @@ static void snake_upcase_char(char *c)
|
|
67
68
|
parser->request_path(parser, PTR_TO(mark), LEN(mark,fpc));
|
68
69
|
}
|
69
70
|
|
70
|
-
action done {
|
71
|
-
parser->body_start = fpc - buffer + 1;
|
71
|
+
action done {
|
72
|
+
parser->body_start = fpc - buffer + 1;
|
72
73
|
parser->header_done(parser, fpc + 1, pe - fpc - 1);
|
73
74
|
fbreak;
|
74
75
|
}
|
75
76
|
|
76
|
-
include
|
77
|
+
include puma_parser_common "http11_parser_common.rl";
|
77
78
|
|
78
79
|
}%%
|
79
80
|
|
80
81
|
/** Data **/
|
81
82
|
%% write data;
|
82
83
|
|
83
|
-
int
|
84
|
+
int puma_parser_init(puma_parser *parser) {
|
84
85
|
int cs = 0;
|
85
86
|
%% write init;
|
86
87
|
parser->cs = cs;
|
@@ -98,7 +99,7 @@ int http_parser_init(http_parser *parser) {
|
|
98
99
|
|
99
100
|
|
100
101
|
/** exec **/
|
101
|
-
size_t
|
102
|
+
size_t puma_parser_execute(puma_parser *parser, const char *buffer, size_t len, size_t off) {
|
102
103
|
const char *p, *pe;
|
103
104
|
int cs = parser->cs;
|
104
105
|
|
@@ -108,11 +109,11 @@ size_t http_parser_execute(http_parser *parser, const char *buffer, size_t len,
|
|
108
109
|
pe = buffer+len;
|
109
110
|
|
110
111
|
/* assert(*pe == '\0' && "pointer does not end on NUL"); */
|
111
|
-
assert(pe - p == len - off && "pointers aren't same distance");
|
112
|
+
assert((size_t) (pe - p) == len - off && "pointers aren't same distance");
|
112
113
|
|
113
114
|
%% write exec;
|
114
115
|
|
115
|
-
if (!
|
116
|
+
if (!puma_parser_has_error(parser))
|
116
117
|
parser->cs = cs;
|
117
118
|
parser->nread += p - (buffer + off);
|
118
119
|
|
@@ -126,21 +127,21 @@ size_t http_parser_execute(http_parser *parser, const char *buffer, size_t len,
|
|
126
127
|
return(parser->nread);
|
127
128
|
}
|
128
129
|
|
129
|
-
int
|
130
|
+
int puma_parser_finish(puma_parser *parser)
|
130
131
|
{
|
131
|
-
if (
|
132
|
+
if (puma_parser_has_error(parser) ) {
|
132
133
|
return -1;
|
133
|
-
} else if (
|
134
|
+
} else if (puma_parser_is_finished(parser) ) {
|
134
135
|
return 1;
|
135
136
|
} else {
|
136
137
|
return 0;
|
137
138
|
}
|
138
139
|
}
|
139
140
|
|
140
|
-
int
|
141
|
-
return parser->cs ==
|
141
|
+
int puma_parser_has_error(puma_parser *parser) {
|
142
|
+
return parser->cs == puma_parser_error;
|
142
143
|
}
|
143
144
|
|
144
|
-
int
|
145
|
-
return parser->cs >=
|
145
|
+
int puma_parser_is_finished(puma_parser *parser) {
|
146
|
+
return parser->cs >= puma_parser_first_final;
|
146
147
|
}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
%%{
|
2
|
-
|
3
|
-
machine
|
2
|
+
|
3
|
+
machine puma_parser_common;
|
4
4
|
|
5
5
|
#### HTTP PROTOCOL GRAMMAR
|
6
6
|
# line endings
|
@@ -15,8 +15,8 @@
|
|
15
15
|
national = any -- (alpha | digit | reserved | extra | safe | unsafe);
|
16
16
|
unreserved = (alpha | digit | safe | extra | national);
|
17
17
|
escape = ("%" xdigit xdigit);
|
18
|
-
uchar = (unreserved | escape);
|
19
|
-
pchar = (uchar | ":" | "@" | "&" | "=" | "+");
|
18
|
+
uchar = (unreserved | escape | "%");
|
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
@@ -1,8 +1,25 @@
|
|
1
|
+
#define RSTRING_NOT_MODIFIED 1
|
2
|
+
|
1
3
|
#include <ruby.h>
|
4
|
+
#include <ruby/version.h>
|
5
|
+
|
6
|
+
#if RUBY_API_VERSION_MAJOR == 1
|
2
7
|
#include <rubyio.h>
|
8
|
+
#else
|
9
|
+
#include <ruby/io.h>
|
10
|
+
#endif
|
11
|
+
|
12
|
+
#ifdef HAVE_OPENSSL_BIO_H
|
13
|
+
|
3
14
|
#include <openssl/bio.h>
|
4
15
|
#include <openssl/ssl.h>
|
16
|
+
#include <openssl/dh.h>
|
5
17
|
#include <openssl/err.h>
|
18
|
+
#include <openssl/x509.h>
|
19
|
+
|
20
|
+
#ifndef SSL_OP_NO_COMPRESSION
|
21
|
+
#define SSL_OP_NO_COMPRESSION 0
|
22
|
+
#endif
|
6
23
|
|
7
24
|
typedef struct {
|
8
25
|
BIO* read;
|
@@ -11,9 +28,19 @@ typedef struct {
|
|
11
28
|
SSL_CTX* ctx;
|
12
29
|
} ms_conn;
|
13
30
|
|
31
|
+
typedef struct {
|
32
|
+
unsigned char* buf;
|
33
|
+
int bytes;
|
34
|
+
} ms_cert_buf;
|
35
|
+
|
14
36
|
void engine_free(ms_conn* conn) {
|
15
|
-
|
16
|
-
|
37
|
+
ms_cert_buf* cert_buf = (ms_cert_buf*)SSL_get_app_data(conn->ssl);
|
38
|
+
if(cert_buf) {
|
39
|
+
OPENSSL_free(cert_buf->buf);
|
40
|
+
free(cert_buf);
|
41
|
+
}
|
42
|
+
SSL_free(conn->ssl);
|
43
|
+
SSL_CTX_free(conn->ctx);
|
17
44
|
|
18
45
|
free(conn);
|
19
46
|
}
|
@@ -35,27 +62,196 @@ ms_conn* engine_alloc(VALUE klass, VALUE* obj) {
|
|
35
62
|
return conn;
|
36
63
|
}
|
37
64
|
|
38
|
-
|
65
|
+
DH *get_dh1024() {
|
66
|
+
/* `openssl dhparam 1024 -C`
|
67
|
+
* -----BEGIN DH PARAMETERS-----
|
68
|
+
* MIGHAoGBALPwcEv0OstmQCZdfHw0N5r+07lmXMxkpQacy1blwj0LUqC+Divp6pBk
|
69
|
+
* usTJ9W2/dOYr1X7zi6yXNLp4oLzc/31PUL3D9q8CpGS7vPz5gijKSw9BwCTT5z9+
|
70
|
+
* KF9v46qw8XqT5HHV87sWFlGQcVFq+pEkA2kPikkKZ/X/CCcpCAV7AgEC
|
71
|
+
* -----END DH PARAMETERS-----
|
72
|
+
*/
|
73
|
+
static unsigned char dh1024_p[] = {
|
74
|
+
0xB3,0xF0,0x70,0x4B,0xF4,0x3A,0xCB,0x66,0x40,0x26,0x5D,0x7C,
|
75
|
+
0x7C,0x34,0x37,0x9A,0xFE,0xD3,0xB9,0x66,0x5C,0xCC,0x64,0xA5,
|
76
|
+
0x06,0x9C,0xCB,0x56,0xE5,0xC2,0x3D,0x0B,0x52,0xA0,0xBE,0x0E,
|
77
|
+
0x2B,0xE9,0xEA,0x90,0x64,0xBA,0xC4,0xC9,0xF5,0x6D,0xBF,0x74,
|
78
|
+
0xE6,0x2B,0xD5,0x7E,0xF3,0x8B,0xAC,0x97,0x34,0xBA,0x78,0xA0,
|
79
|
+
0xBC,0xDC,0xFF,0x7D,0x4F,0x50,0xBD,0xC3,0xF6,0xAF,0x02,0xA4,
|
80
|
+
0x64,0xBB,0xBC,0xFC,0xF9,0x82,0x28,0xCA,0x4B,0x0F,0x41,0xC0,
|
81
|
+
0x24,0xD3,0xE7,0x3F,0x7E,0x28,0x5F,0x6F,0xE3,0xAA,0xB0,0xF1,
|
82
|
+
0x7A,0x93,0xE4,0x71,0xD5,0xF3,0xBB,0x16,0x16,0x51,0x90,0x71,
|
83
|
+
0x51,0x6A,0xFA,0x91,0x24,0x03,0x69,0x0F,0x8A,0x49,0x0A,0x67,
|
84
|
+
0xF5,0xFF,0x08,0x27,0x29,0x08,0x05,0x7B
|
85
|
+
};
|
86
|
+
static unsigned char dh1024_g[] = { 0x02 };
|
87
|
+
|
88
|
+
DH *dh;
|
89
|
+
dh = DH_new();
|
90
|
+
|
91
|
+
#if OPENSSL_VERSION_NUMBER < 0x10100005L || defined(LIBRESSL_VERSION_NUMBER)
|
92
|
+
dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
|
93
|
+
dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
|
94
|
+
|
95
|
+
if ((dh->p == NULL) || (dh->g == NULL)) {
|
96
|
+
DH_free(dh);
|
97
|
+
return NULL;
|
98
|
+
}
|
99
|
+
#else
|
100
|
+
BIGNUM *p, *g;
|
101
|
+
p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
|
102
|
+
g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
|
103
|
+
|
104
|
+
if (p == NULL || g == NULL || !DH_set0_pqg(dh, p, NULL, g)) {
|
105
|
+
DH_free(dh);
|
106
|
+
BN_free(p);
|
107
|
+
BN_free(g);
|
108
|
+
return NULL;
|
109
|
+
}
|
110
|
+
#endif
|
111
|
+
|
112
|
+
return dh;
|
113
|
+
}
|
114
|
+
|
115
|
+
static int engine_verify_callback(int preverify_ok, X509_STORE_CTX* ctx) {
|
116
|
+
X509* err_cert;
|
117
|
+
SSL* ssl;
|
118
|
+
int bytes;
|
119
|
+
unsigned char* buf = NULL;
|
120
|
+
|
121
|
+
if(!preverify_ok) {
|
122
|
+
err_cert = X509_STORE_CTX_get_current_cert(ctx);
|
123
|
+
if(err_cert) {
|
124
|
+
/*
|
125
|
+
* Save the failed certificate for inspection/logging.
|
126
|
+
*/
|
127
|
+
bytes = i2d_X509(err_cert, &buf);
|
128
|
+
if(bytes > 0) {
|
129
|
+
ms_cert_buf* cert_buf = (ms_cert_buf*)malloc(sizeof(ms_cert_buf));
|
130
|
+
cert_buf->buf = buf;
|
131
|
+
cert_buf->bytes = bytes;
|
132
|
+
ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
|
133
|
+
SSL_set_app_data(ssl, cert_buf);
|
134
|
+
}
|
135
|
+
}
|
136
|
+
}
|
137
|
+
|
138
|
+
return preverify_ok;
|
139
|
+
}
|
140
|
+
|
141
|
+
VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) {
|
39
142
|
VALUE obj;
|
40
143
|
SSL_CTX* ctx;
|
41
144
|
SSL* ssl;
|
145
|
+
int min, ssl_options;
|
42
146
|
|
43
147
|
ms_conn* conn = engine_alloc(self, &obj);
|
44
148
|
|
149
|
+
ID sym_key = rb_intern("key");
|
150
|
+
VALUE key = rb_funcall(mini_ssl_ctx, sym_key, 0);
|
151
|
+
|
45
152
|
StringValue(key);
|
153
|
+
|
154
|
+
ID sym_cert = rb_intern("cert");
|
155
|
+
VALUE cert = rb_funcall(mini_ssl_ctx, sym_cert, 0);
|
156
|
+
|
46
157
|
StringValue(cert);
|
47
158
|
|
159
|
+
ID sym_ca = rb_intern("ca");
|
160
|
+
VALUE ca = rb_funcall(mini_ssl_ctx, sym_ca, 0);
|
161
|
+
|
162
|
+
ID sym_verify_mode = rb_intern("verify_mode");
|
163
|
+
VALUE verify_mode = rb_funcall(mini_ssl_ctx, sym_verify_mode, 0);
|
164
|
+
|
165
|
+
ID sym_ssl_cipher_filter = rb_intern("ssl_cipher_filter");
|
166
|
+
VALUE ssl_cipher_filter = rb_funcall(mini_ssl_ctx, sym_ssl_cipher_filter, 0);
|
167
|
+
|
168
|
+
ID sym_no_tlsv1 = rb_intern("no_tlsv1");
|
169
|
+
VALUE no_tlsv1 = rb_funcall(mini_ssl_ctx, sym_no_tlsv1, 0);
|
170
|
+
|
171
|
+
ID sym_no_tlsv1_1 = rb_intern("no_tlsv1_1");
|
172
|
+
VALUE no_tlsv1_1 = rb_funcall(mini_ssl_ctx, sym_no_tlsv1_1, 0);
|
173
|
+
|
174
|
+
#ifdef HAVE_TLS_SERVER_METHOD
|
175
|
+
ctx = SSL_CTX_new(TLS_server_method());
|
176
|
+
#else
|
48
177
|
ctx = SSL_CTX_new(SSLv23_server_method());
|
178
|
+
#endif
|
49
179
|
conn->ctx = ctx;
|
50
180
|
|
51
|
-
|
181
|
+
SSL_CTX_use_certificate_chain_file(ctx, RSTRING_PTR(cert));
|
52
182
|
SSL_CTX_use_PrivateKey_file(ctx, RSTRING_PTR(key), SSL_FILETYPE_PEM);
|
53
|
-
/* SSL_CTX_set_options(ctx, SSL_OP_SINGLE_DH_USE); */
|
54
183
|
|
55
|
-
|
184
|
+
if (!NIL_P(ca)) {
|
185
|
+
StringValue(ca);
|
186
|
+
SSL_CTX_load_verify_locations(ctx, RSTRING_PTR(ca), NULL);
|
187
|
+
}
|
188
|
+
|
189
|
+
ssl_options = SSL_OP_CIPHER_SERVER_PREFERENCE | SSL_OP_SINGLE_ECDH_USE | SSL_OP_NO_COMPRESSION;
|
190
|
+
|
191
|
+
#ifdef HAVE_SSL_CTX_SET_MIN_PROTO_VERSION
|
192
|
+
if (RTEST(no_tlsv1_1)) {
|
193
|
+
min = TLS1_2_VERSION;
|
194
|
+
}
|
195
|
+
else if (RTEST(no_tlsv1)) {
|
196
|
+
min = TLS1_1_VERSION;
|
197
|
+
}
|
198
|
+
else {
|
199
|
+
min = TLS1_VERSION;
|
200
|
+
}
|
201
|
+
|
202
|
+
SSL_CTX_set_min_proto_version(ctx, min);
|
203
|
+
|
204
|
+
SSL_CTX_set_options(ctx, ssl_options);
|
205
|
+
|
206
|
+
#else
|
207
|
+
/* As of 1.0.2f, SSL_OP_SINGLE_DH_USE key use is always on */
|
208
|
+
ssl_options |= SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_SINGLE_DH_USE;
|
209
|
+
|
210
|
+
if (RTEST(no_tlsv1)) {
|
211
|
+
ssl_options |= SSL_OP_NO_TLSv1;
|
212
|
+
}
|
213
|
+
if(RTEST(no_tlsv1_1)) {
|
214
|
+
ssl_options |= SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1;
|
215
|
+
}
|
216
|
+
SSL_CTX_set_options(ctx, ssl_options);
|
217
|
+
#endif
|
218
|
+
|
219
|
+
SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
|
220
|
+
|
221
|
+
if (!NIL_P(ssl_cipher_filter)) {
|
222
|
+
StringValue(ssl_cipher_filter);
|
223
|
+
SSL_CTX_set_cipher_list(ctx, RSTRING_PTR(ssl_cipher_filter));
|
224
|
+
}
|
225
|
+
else {
|
226
|
+
SSL_CTX_set_cipher_list(ctx, "HIGH:!aNULL@STRENGTH");
|
227
|
+
}
|
228
|
+
|
229
|
+
DH *dh = get_dh1024();
|
230
|
+
SSL_CTX_set_tmp_dh(ctx, dh);
|
231
|
+
|
232
|
+
#if OPENSSL_VERSION_NUMBER < 0x10002000L
|
233
|
+
// Remove this case if OpenSSL 1.0.1 (now EOL) support is no
|
234
|
+
// longer needed.
|
235
|
+
EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
|
236
|
+
if (ecdh) {
|
237
|
+
SSL_CTX_set_tmp_ecdh(ctx, ecdh);
|
238
|
+
EC_KEY_free(ecdh);
|
239
|
+
}
|
240
|
+
#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
|
+
SSL_CTX_set_ecdh_auto(ctx, 1);
|
244
|
+
#endif
|
245
|
+
|
246
|
+
ssl = SSL_new(ctx);
|
56
247
|
conn->ssl = ssl;
|
248
|
+
SSL_set_app_data(ssl, NULL);
|
57
249
|
|
58
|
-
|
250
|
+
if (NIL_P(verify_mode)) {
|
251
|
+
/* SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL); */
|
252
|
+
} else {
|
253
|
+
SSL_set_verify(ssl, NUM2INT(verify_mode), engine_verify_callback);
|
254
|
+
}
|
59
255
|
|
60
256
|
SSL_set_bio(ssl, conn->read, conn->write);
|
61
257
|
|
@@ -66,9 +262,13 @@ VALUE engine_init_server(VALUE self, VALUE key, VALUE cert) {
|
|
66
262
|
VALUE engine_init_client(VALUE klass) {
|
67
263
|
VALUE obj;
|
68
264
|
ms_conn* conn = engine_alloc(klass, &obj);
|
69
|
-
|
265
|
+
#ifdef HAVE_DTLS_METHOD
|
266
|
+
conn->ctx = SSL_CTX_new(DTLS_method());
|
267
|
+
#else
|
70
268
|
conn->ctx = SSL_CTX_new(DTLSv1_method());
|
269
|
+
#endif
|
71
270
|
conn->ssl = SSL_new(conn->ctx);
|
271
|
+
SSL_set_app_data(conn->ssl, NULL);
|
72
272
|
SSL_set_verify(conn->ssl, SSL_VERIFY_NONE, NULL);
|
73
273
|
|
74
274
|
SSL_set_bio(conn->ssl, conn->read, conn->write);
|
@@ -97,20 +297,46 @@ VALUE engine_inject(VALUE self, VALUE str) {
|
|
97
297
|
static VALUE eError;
|
98
298
|
|
99
299
|
void raise_error(SSL* ssl, int result) {
|
100
|
-
|
101
|
-
char
|
300
|
+
char buf[512];
|
301
|
+
char msg[512];
|
302
|
+
const char* err_str;
|
303
|
+
int err = errno;
|
304
|
+
int ssl_err = SSL_get_error(ssl, result);
|
305
|
+
int verify_err = (int) SSL_get_verify_result(ssl);
|
306
|
+
|
307
|
+
if(SSL_ERROR_SYSCALL == ssl_err) {
|
308
|
+
snprintf(msg, sizeof(msg), "System error: %s - %d", strerror(err), err);
|
309
|
+
|
310
|
+
} else if(SSL_ERROR_SSL == ssl_err) {
|
311
|
+
if(X509_V_OK != verify_err) {
|
312
|
+
err_str = X509_verify_cert_error_string(verify_err);
|
313
|
+
snprintf(msg, sizeof(msg),
|
314
|
+
"OpenSSL certificate verification error: %s - %d",
|
315
|
+
err_str, verify_err);
|
316
|
+
|
317
|
+
} else {
|
318
|
+
err = (int) ERR_get_error();
|
319
|
+
ERR_error_string_n(err, buf, sizeof(buf));
|
320
|
+
snprintf(msg, sizeof(msg), "OpenSSL error: %s - %d", buf, err);
|
321
|
+
|
322
|
+
}
|
323
|
+
} else {
|
324
|
+
snprintf(msg, sizeof(msg), "Unknown OpenSSL error: %d", ssl_err);
|
325
|
+
}
|
102
326
|
|
103
327
|
ERR_clear_error();
|
104
|
-
rb_raise(eError, "
|
328
|
+
rb_raise(eError, "%s", msg);
|
105
329
|
}
|
106
330
|
|
107
331
|
VALUE engine_read(VALUE self) {
|
108
332
|
ms_conn* conn;
|
109
333
|
char buf[512];
|
110
|
-
int bytes,
|
334
|
+
int bytes, error;
|
111
335
|
|
112
336
|
Data_Get_Struct(self, ms_conn, conn);
|
113
337
|
|
338
|
+
ERR_clear_error();
|
339
|
+
|
114
340
|
bytes = SSL_read(conn->ssl, (void*)buf, sizeof(buf));
|
115
341
|
|
116
342
|
if(bytes > 0) {
|
@@ -119,24 +345,27 @@ VALUE engine_read(VALUE self) {
|
|
119
345
|
|
120
346
|
if(SSL_want_read(conn->ssl)) return Qnil;
|
121
347
|
|
122
|
-
|
348
|
+
error = SSL_get_error(conn->ssl, bytes);
|
349
|
+
|
350
|
+
if(error == SSL_ERROR_ZERO_RETURN) {
|
123
351
|
rb_eof_error();
|
352
|
+
} else {
|
353
|
+
raise_error(conn->ssl, bytes);
|
124
354
|
}
|
125
355
|
|
126
|
-
raise_error(conn->ssl, bytes);
|
127
|
-
|
128
356
|
return Qnil;
|
129
357
|
}
|
130
358
|
|
131
359
|
VALUE engine_write(VALUE self, VALUE str) {
|
132
360
|
ms_conn* conn;
|
133
|
-
char buf[512];
|
134
361
|
int bytes;
|
135
362
|
|
136
363
|
Data_Get_Struct(self, ms_conn, conn);
|
137
364
|
|
138
365
|
StringValue(str);
|
139
366
|
|
367
|
+
ERR_clear_error();
|
368
|
+
|
140
369
|
bytes = SSL_write(conn->ssl, (void*)RSTRING_PTR(str), (int)RSTRING_LEN(str));
|
141
370
|
if(bytes > 0) {
|
142
371
|
return INT2FIX(bytes);
|
@@ -170,20 +399,127 @@ VALUE engine_extract(VALUE self) {
|
|
170
399
|
return Qnil;
|
171
400
|
}
|
172
401
|
|
402
|
+
VALUE engine_shutdown(VALUE self) {
|
403
|
+
ms_conn* conn;
|
404
|
+
int ok;
|
405
|
+
|
406
|
+
Data_Get_Struct(self, ms_conn, conn);
|
407
|
+
|
408
|
+
ERR_clear_error();
|
409
|
+
|
410
|
+
ok = SSL_shutdown(conn->ssl);
|
411
|
+
if (ok == 0) {
|
412
|
+
return Qfalse;
|
413
|
+
}
|
414
|
+
|
415
|
+
return Qtrue;
|
416
|
+
}
|
417
|
+
|
418
|
+
VALUE engine_init(VALUE self) {
|
419
|
+
ms_conn* conn;
|
420
|
+
|
421
|
+
Data_Get_Struct(self, ms_conn, conn);
|
422
|
+
|
423
|
+
return SSL_in_init(conn->ssl) ? Qtrue : Qfalse;
|
424
|
+
}
|
425
|
+
|
426
|
+
VALUE engine_peercert(VALUE self) {
|
427
|
+
ms_conn* conn;
|
428
|
+
X509* cert;
|
429
|
+
int bytes;
|
430
|
+
unsigned char* buf = NULL;
|
431
|
+
ms_cert_buf* cert_buf = NULL;
|
432
|
+
VALUE rb_cert_buf;
|
433
|
+
|
434
|
+
Data_Get_Struct(self, ms_conn, conn);
|
435
|
+
|
436
|
+
cert = SSL_get_peer_certificate(conn->ssl);
|
437
|
+
if(!cert) {
|
438
|
+
/*
|
439
|
+
* See if there was a failed certificate associated with this client.
|
440
|
+
*/
|
441
|
+
cert_buf = (ms_cert_buf*)SSL_get_app_data(conn->ssl);
|
442
|
+
if(!cert_buf) {
|
443
|
+
return Qnil;
|
444
|
+
}
|
445
|
+
buf = cert_buf->buf;
|
446
|
+
bytes = cert_buf->bytes;
|
447
|
+
|
448
|
+
} else {
|
449
|
+
bytes = i2d_X509(cert, &buf);
|
450
|
+
X509_free(cert);
|
451
|
+
|
452
|
+
if(bytes < 0) {
|
453
|
+
return Qnil;
|
454
|
+
}
|
455
|
+
}
|
456
|
+
|
457
|
+
rb_cert_buf = rb_str_new((const char*)(buf), bytes);
|
458
|
+
if(!cert_buf) {
|
459
|
+
OPENSSL_free(buf);
|
460
|
+
}
|
461
|
+
|
462
|
+
return rb_cert_buf;
|
463
|
+
}
|
464
|
+
|
465
|
+
VALUE noop(VALUE self) {
|
466
|
+
return Qnil;
|
467
|
+
}
|
468
|
+
|
173
469
|
void Init_mini_ssl(VALUE puma) {
|
174
470
|
VALUE mod, eng;
|
175
471
|
|
472
|
+
/* Fake operation for documentation (RDoc, YARD) */
|
473
|
+
#if 0 == 1
|
474
|
+
puma = rb_define_module("Puma");
|
475
|
+
#endif
|
476
|
+
|
176
477
|
SSL_library_init();
|
177
478
|
OpenSSL_add_ssl_algorithms();
|
178
479
|
SSL_load_error_strings();
|
179
480
|
ERR_load_crypto_strings();
|
180
|
-
|
481
|
+
|
181
482
|
mod = rb_define_module_under(puma, "MiniSSL");
|
182
483
|
eng = rb_define_class_under(mod, "Engine", rb_cObject);
|
183
484
|
|
485
|
+
// OpenSSL Build / Runtime/Load versions
|
486
|
+
|
487
|
+
/* Version of OpenSSL that Puma was compiled with */
|
488
|
+
rb_define_const(mod, "OPENSSL_VERSION", rb_str_new2(OPENSSL_VERSION_TEXT));
|
489
|
+
|
490
|
+
#if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000
|
491
|
+
/* Version of OpenSSL that Puma loaded with */
|
492
|
+
rb_define_const(mod, "OPENSSL_LIBRARY_VERSION", rb_str_new2(OpenSSL_version(OPENSSL_VERSION)));
|
493
|
+
#else
|
494
|
+
rb_define_const(mod, "OPENSSL_LIBRARY_VERSION", rb_str_new2(SSLeay_version(SSLEAY_VERSION)));
|
495
|
+
#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
|
517
|
+
|
518
|
+
rb_define_singleton_method(mod, "check", noop, 0);
|
519
|
+
|
184
520
|
eError = rb_define_class_under(mod, "SSLError", rb_eStandardError);
|
185
521
|
|
186
|
-
rb_define_singleton_method(eng, "server", engine_init_server,
|
522
|
+
rb_define_singleton_method(eng, "server", engine_init_server, 1);
|
187
523
|
rb_define_singleton_method(eng, "client", engine_init_client, 0);
|
188
524
|
|
189
525
|
rb_define_method(eng, "inject", engine_inject, 1);
|
@@ -191,4 +527,27 @@ void Init_mini_ssl(VALUE puma) {
|
|
191
527
|
|
192
528
|
rb_define_method(eng, "write", engine_write, 1);
|
193
529
|
rb_define_method(eng, "extract", engine_extract, 0);
|
530
|
+
|
531
|
+
rb_define_method(eng, "shutdown", engine_shutdown, 0);
|
532
|
+
|
533
|
+
rb_define_method(eng, "init?", engine_init, 0);
|
534
|
+
|
535
|
+
rb_define_method(eng, "peercert", engine_peercert, 0);
|
536
|
+
}
|
537
|
+
|
538
|
+
#else
|
539
|
+
|
540
|
+
VALUE raise_error(VALUE self) {
|
541
|
+
rb_raise(rb_eStandardError, "SSL not available in this build");
|
542
|
+
return Qnil;
|
543
|
+
}
|
544
|
+
|
545
|
+
void Init_mini_ssl(VALUE puma) {
|
546
|
+
VALUE mod;
|
547
|
+
|
548
|
+
mod = rb_define_module_under(puma, "MiniSSL");
|
549
|
+
rb_define_class_under(mod, "SSLError", rb_eStandardError);
|
550
|
+
|
551
|
+
rb_define_singleton_method(mod, "check", raise_error, 0);
|
194
552
|
}
|
553
|
+
#endif
|