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.

Files changed (96) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +1553 -447
  3. data/LICENSE +23 -20
  4. data/README.md +175 -63
  5. data/bin/puma-wild +3 -9
  6. data/docs/architecture.md +59 -21
  7. data/docs/compile_options.md +21 -0
  8. data/docs/deployment.md +69 -58
  9. data/docs/fork_worker.md +33 -0
  10. data/docs/images/puma-connection-flow-no-reactor.png +0 -0
  11. data/docs/images/puma-connection-flow.png +0 -0
  12. data/docs/images/puma-general-arch.png +0 -0
  13. data/docs/jungle/README.md +9 -0
  14. data/{tools → docs}/jungle/rc.d/README.md +1 -1
  15. data/{tools → docs}/jungle/rc.d/puma +2 -2
  16. data/{tools → docs}/jungle/rc.d/puma.conf +0 -0
  17. data/docs/kubernetes.md +66 -0
  18. data/docs/nginx.md +1 -1
  19. data/docs/plugins.md +22 -12
  20. data/docs/rails_dev_mode.md +28 -0
  21. data/docs/restart.md +47 -22
  22. data/docs/signals.md +13 -11
  23. data/docs/stats.md +142 -0
  24. data/docs/systemd.md +95 -120
  25. data/ext/puma_http11/PumaHttp11Service.java +2 -2
  26. data/ext/puma_http11/ext_help.h +1 -1
  27. data/ext/puma_http11/extconf.rb +51 -1
  28. data/ext/puma_http11/http11_parser.c +105 -117
  29. data/ext/puma_http11/http11_parser.h +1 -1
  30. data/ext/puma_http11/http11_parser.java.rl +22 -38
  31. data/ext/puma_http11/http11_parser.rl +4 -2
  32. data/ext/puma_http11/http11_parser_common.rl +4 -4
  33. data/ext/puma_http11/mini_ssl.c +319 -96
  34. data/ext/puma_http11/no_ssl/PumaHttp11Service.java +15 -0
  35. data/ext/puma_http11/org/jruby/puma/Http11.java +108 -116
  36. data/ext/puma_http11/org/jruby/puma/Http11Parser.java +84 -99
  37. data/ext/puma_http11/org/jruby/puma/MiniSSL.java +120 -65
  38. data/ext/puma_http11/puma_http11.c +35 -51
  39. data/lib/puma/app/status.rb +68 -49
  40. data/lib/puma/binder.rb +234 -137
  41. data/lib/puma/cli.rb +28 -18
  42. data/lib/puma/client.rb +343 -230
  43. data/lib/puma/cluster/worker.rb +173 -0
  44. data/lib/puma/cluster/worker_handle.rb +94 -0
  45. data/lib/puma/cluster.rb +247 -232
  46. data/lib/puma/commonlogger.rb +2 -2
  47. data/lib/puma/configuration.rb +61 -51
  48. data/lib/puma/const.rb +42 -21
  49. data/lib/puma/control_cli.rb +109 -67
  50. data/lib/puma/detect.rb +29 -2
  51. data/lib/puma/dsl.rb +615 -123
  52. data/lib/puma/error_logger.rb +104 -0
  53. data/lib/puma/events.rb +55 -31
  54. data/lib/puma/io_buffer.rb +7 -5
  55. data/lib/puma/jruby_restart.rb +0 -58
  56. data/lib/puma/json_serialization.rb +96 -0
  57. data/lib/puma/launcher.rb +182 -69
  58. data/lib/puma/minissl/context_builder.rb +81 -0
  59. data/lib/puma/minissl.rb +161 -61
  60. data/lib/puma/null_io.rb +13 -1
  61. data/lib/puma/plugin/tmp_restart.rb +2 -0
  62. data/lib/puma/plugin.rb +7 -13
  63. data/lib/puma/queue_close.rb +26 -0
  64. data/lib/puma/rack/builder.rb +3 -5
  65. data/lib/puma/rack/urlmap.rb +2 -0
  66. data/lib/puma/rack_default.rb +2 -0
  67. data/lib/puma/reactor.rb +85 -316
  68. data/lib/puma/request.rb +472 -0
  69. data/lib/puma/runner.rb +48 -55
  70. data/lib/puma/server.rb +303 -695
  71. data/lib/puma/single.rb +11 -67
  72. data/lib/puma/state_file.rb +47 -8
  73. data/lib/puma/systemd.rb +46 -0
  74. data/lib/puma/thread_pool.rb +132 -82
  75. data/lib/puma/util.rb +21 -7
  76. data/lib/puma.rb +54 -0
  77. data/lib/rack/handler/puma.rb +5 -6
  78. data/tools/Dockerfile +16 -0
  79. data/tools/trickletest.rb +0 -1
  80. metadata +45 -29
  81. data/ext/puma_http11/io_buffer.c +0 -155
  82. data/lib/puma/accept_nonblock.rb +0 -23
  83. data/lib/puma/compat.rb +0 -14
  84. data/lib/puma/convenient.rb +0 -25
  85. data/lib/puma/daemon_ext.rb +0 -33
  86. data/lib/puma/delegation.rb +0 -13
  87. data/lib/puma/java_io_buffer.rb +0 -47
  88. data/lib/puma/rack/backports/uri/common_193.rb +0 -33
  89. data/lib/puma/tcp_logger.rb +0 -41
  90. data/tools/jungle/README.md +0 -19
  91. data/tools/jungle/init.d/README.md +0 -61
  92. data/tools/jungle/init.d/puma +0 -421
  93. data/tools/jungle/init.d/run-puma +0 -18
  94. data/tools/jungle/upstart/README.md +0 -61
  95. data/tools/jungle/upstart/puma-manager.conf +0 -31
  96. 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 (";" params)? ) ("?" %start_query query)?;
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
 
@@ -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
- void engine_free(ms_conn* conn) {
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
- ms_conn* engine_alloc(VALUE klass, VALUE* obj) {
49
- ms_conn* conn;
50
-
51
- *obj = Data_Make_Struct(klass, ms_conn, 0, engine_free, conn);
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
- conn->ssl = 0;
60
- conn->ctx = 0;
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
- * MIGHAoGBALPwcEv0OstmQCZdfHw0N5r+07lmXMxkpQacy1blwj0LUqC+Divp6pBk
69
- * usTJ9W2/dOYr1X7zi6yXNLp4oLzc/31PUL3D9q8CpGS7vPz5gijKSw9BwCTT5z9+
70
- * KF9v46qw8XqT5HHV87sWFlGQcVFq+pEkA2kPikkKZ/X/CCcpCAV7AgEC
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 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
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 dh1024_g[] = { 0x02 };
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(dh1024_p, sizeof(dh1024_p), NULL);
93
- dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
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
- BIGNUM *p, *g;
101
- p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
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
- VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) {
142
- VALUE obj;
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
- ms_conn* conn = engine_alloc(self, &obj);
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
- ID sym_key = rb_intern("key");
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
- StringValue(key);
229
+ cert = rb_funcall(mini_ssl_ctx, rb_intern_const("cert"), 0);
152
230
 
153
- ID sym_cert = rb_intern("cert");
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
- StringValue(cert);
233
+ cert_pem = rb_funcall(mini_ssl_ctx, rb_intern_const("cert_pem"), 0);
157
234
 
158
- ID sym_ca = rb_intern("ca");
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
- ID sym_verify_mode = rb_intern("verify_mode");
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
- ID sym_ssl_cipher_filter = rb_intern("ssl_cipher_filter");
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
- ctx = SSL_CTX_new(SSLv23_server_method());
168
- conn->ctx = ctx;
241
+ no_tlsv1 = rb_funcall(mini_ssl_ctx, rb_intern_const("no_tlsv1"), 0);
169
242
 
170
- SSL_CTX_use_certificate_chain_file(ctx, RSTRING_PTR(cert));
171
- SSL_CTX_use_PrivateKey_file(ctx, RSTRING_PTR(key), SSL_FILETYPE_PEM);
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
- SSL_CTX_set_options(ctx, SSL_OP_CIPHER_SERVER_PREFERENCE | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_SINGLE_DH_USE | SSL_OP_SINGLE_ECDH_USE | SSL_OP_NO_COMPRESSION);
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
- DH *dh = get_dh1024();
190
- SSL_CTX_set_tmp_dh(ctx, dh);
191
-
192
- #ifndef OPENSSL_NO_ECDH
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
- /* SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL); */
337
+ /* SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); */
206
338
  } else {
207
- SSL_set_verify(ssl, NUM2INT(verify_mode), engine_verify_callback);
339
+ SSL_CTX_set_verify(ctx, NUM2INT(verify_mode), engine_verify_callback);
208
340
  }
209
341
 
210
- SSL_set_bio(ssl, conn->read, conn->write);
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
- Data_Get_Struct(self, ms_conn, conn);
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
- static VALUE eError;
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
- Data_Get_Struct(self, ms_conn, conn);
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
- Data_Get_Struct(self, ms_conn, conn);
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
- char buf[512];
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
- Data_Get_Struct(self, ms_conn, conn);
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
- Data_Get_Struct(self, ms_conn, conn);
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
- Data_Get_Struct(self, ms_conn, conn);
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
- Data_Get_Struct(self, ms_conn, conn);
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
- rb_define_const(mod, "OPENSSL_VERSION", rb_str_new2(OPENSSL_VERSION_TEXT));
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
- /* Version of OpenSSL that Puma loaded with */
443
- rb_define_const(mod, "OPENSSL_LIBRARY_VERSION", rb_str_new2(OpenSSL_version(OPENSSL_VERSION)));
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
- rb_define_const(mod, "OPENSSL_LIBRARY_VERSION", rb_str_new2(SSLeay_version(SSLEAY_VERSION)));
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
+ }