puma 4.3.8 → 5.6.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +1543 -521
  3. data/LICENSE +23 -20
  4. data/README.md +120 -36
  5. data/bin/puma-wild +3 -9
  6. data/docs/architecture.md +63 -26
  7. data/docs/compile_options.md +21 -0
  8. data/docs/deployment.md +60 -69
  9. data/docs/fork_worker.md +33 -0
  10. data/docs/jungle/README.md +9 -0
  11. data/{tools → docs}/jungle/rc.d/README.md +1 -1
  12. data/{tools → docs}/jungle/rc.d/puma +2 -2
  13. data/docs/kubernetes.md +66 -0
  14. data/docs/nginx.md +1 -1
  15. data/docs/plugins.md +15 -15
  16. data/docs/rails_dev_mode.md +28 -0
  17. data/docs/restart.md +46 -23
  18. data/docs/signals.md +13 -11
  19. data/docs/stats.md +142 -0
  20. data/docs/systemd.md +85 -128
  21. data/ext/puma_http11/PumaHttp11Service.java +2 -4
  22. data/ext/puma_http11/ext_help.h +1 -1
  23. data/ext/puma_http11/extconf.rb +51 -9
  24. data/ext/puma_http11/http11_parser.c +68 -57
  25. data/ext/puma_http11/http11_parser.h +1 -1
  26. data/ext/puma_http11/http11_parser.java.rl +1 -1
  27. data/ext/puma_http11/http11_parser.rl +1 -1
  28. data/ext/puma_http11/http11_parser_common.rl +1 -1
  29. data/ext/puma_http11/mini_ssl.c +295 -124
  30. data/ext/puma_http11/no_ssl/PumaHttp11Service.java +15 -0
  31. data/ext/puma_http11/org/jruby/puma/Http11.java +5 -3
  32. data/ext/puma_http11/org/jruby/puma/Http11Parser.java +51 -51
  33. data/ext/puma_http11/org/jruby/puma/MiniSSL.java +109 -67
  34. data/ext/puma_http11/puma_http11.c +32 -51
  35. data/lib/puma/app/status.rb +50 -36
  36. data/lib/puma/binder.rb +225 -106
  37. data/lib/puma/cli.rb +24 -18
  38. data/lib/puma/client.rb +197 -92
  39. data/lib/puma/cluster/worker.rb +173 -0
  40. data/lib/puma/cluster/worker_handle.rb +94 -0
  41. data/lib/puma/cluster.rb +212 -220
  42. data/lib/puma/commonlogger.rb +2 -2
  43. data/lib/puma/configuration.rb +58 -49
  44. data/lib/puma/const.rb +26 -9
  45. data/lib/puma/control_cli.rb +99 -76
  46. data/lib/puma/detect.rb +29 -2
  47. data/lib/puma/dsl.rb +368 -96
  48. data/lib/puma/error_logger.rb +104 -0
  49. data/lib/puma/events.rb +55 -34
  50. data/lib/puma/io_buffer.rb +9 -2
  51. data/lib/puma/jruby_restart.rb +0 -58
  52. data/lib/puma/json_serialization.rb +96 -0
  53. data/lib/puma/launcher.rb +128 -46
  54. data/lib/puma/minissl/context_builder.rb +14 -9
  55. data/lib/puma/minissl.rb +137 -50
  56. data/lib/puma/null_io.rb +18 -1
  57. data/lib/puma/plugin.rb +3 -12
  58. data/lib/puma/queue_close.rb +26 -0
  59. data/lib/puma/rack/builder.rb +1 -5
  60. data/lib/puma/reactor.rb +85 -369
  61. data/lib/puma/request.rb +489 -0
  62. data/lib/puma/runner.rb +46 -61
  63. data/lib/puma/server.rb +292 -751
  64. data/lib/puma/single.rb +9 -65
  65. data/lib/puma/state_file.rb +48 -8
  66. data/lib/puma/systemd.rb +46 -0
  67. data/lib/puma/thread_pool.rb +125 -57
  68. data/lib/puma/util.rb +32 -4
  69. data/lib/puma.rb +48 -0
  70. data/lib/rack/handler/puma.rb +2 -3
  71. data/lib/rack/version_restriction.rb +15 -0
  72. data/tools/{docker/Dockerfile → Dockerfile} +1 -1
  73. metadata +29 -24
  74. data/docs/tcp_mode.md +0 -96
  75. data/ext/puma_http11/io_buffer.c +0 -155
  76. data/ext/puma_http11/org/jruby/puma/IOBuffer.java +0 -72
  77. data/lib/puma/accept_nonblock.rb +0 -29
  78. data/lib/puma/tcp_logger.rb +0 -41
  79. data/tools/jungle/README.md +0 -19
  80. data/tools/jungle/init.d/README.md +0 -61
  81. data/tools/jungle/init.d/puma +0 -421
  82. data/tools/jungle/init.d/run-puma +0 -18
  83. data/tools/jungle/upstart/README.md +0 -61
  84. data/tools/jungle/upstart/puma-manager.conf +0 -31
  85. data/tools/jungle/upstart/puma.conf +0 -69
  86. /data/{tools → docs}/jungle/rc.d/puma.conf +0 -0
@@ -2,12 +2,7 @@
2
2
 
3
3
  #include <ruby.h>
4
4
  #include <ruby/version.h>
5
-
6
- #if RUBY_API_VERSION_MAJOR == 1
7
- #include <rubyio.h>
8
- #else
9
5
  #include <ruby/io.h>
10
- #endif
11
6
 
12
7
  #ifdef HAVE_OPENSSL_BIO_H
13
8
 
@@ -33,7 +28,16 @@ typedef struct {
33
28
  int bytes;
34
29
  } ms_cert_buf;
35
30
 
36
- void engine_free(ms_conn* conn) {
31
+ VALUE eError;
32
+
33
+ NORETURN(void raise_file_error(const char* caller, const char *filename));
34
+
35
+ void raise_file_error(const char* caller, const char *filename) {
36
+ rb_raise(eError, "%s: error in file '%s': %s", caller, filename, ERR_error_string(ERR_get_error(), NULL));
37
+ }
38
+
39
+ void engine_free(void *ptr) {
40
+ ms_conn *conn = ptr;
37
41
  ms_cert_buf* cert_buf = (ms_cert_buf*)SSL_get_app_data(conn->ssl);
38
42
  if(cert_buf) {
39
43
  OPENSSL_free(cert_buf->buf);
@@ -45,61 +49,72 @@ void engine_free(ms_conn* conn) {
45
49
  free(conn);
46
50
  }
47
51
 
48
- 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);
58
-
59
- conn->ssl = 0;
60
- conn->ctx = 0;
61
-
62
- return conn;
63
- }
52
+ const rb_data_type_t engine_data_type = {
53
+ "MiniSSL/ENGINE",
54
+ { 0, engine_free, 0 },
55
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
56
+ };
64
57
 
65
- DH *get_dh1024() {
66
- /* `openssl dhparam 1024 -C`
58
+ #ifndef HAVE_SSL_CTX_SET_DH_AUTO
59
+ DH *get_dh2048(void) {
60
+ /* `openssl dhparam -C 2048`
67
61
  * -----BEGIN DH PARAMETERS-----
68
- * MIGHAoGBALPwcEv0OstmQCZdfHw0N5r+07lmXMxkpQacy1blwj0LUqC+Divp6pBk
69
- * usTJ9W2/dOYr1X7zi6yXNLp4oLzc/31PUL3D9q8CpGS7vPz5gijKSw9BwCTT5z9+
70
- * KF9v46qw8XqT5HHV87sWFlGQcVFq+pEkA2kPikkKZ/X/CCcpCAV7AgEC
62
+ * MIIBCAKCAQEAjmh1uQHdTfxOyxEbKAV30fUfzqMDF/ChPzjfyzl2jcrqQMhrk76o
63
+ * 2NPNXqxHwsddMZ1RzvU8/jl+uhRuPWjXCFZbhET4N1vrviZM3VJhV8PPHuiVOACO
64
+ * y32jFd+Szx4bo2cXSK83hJ6jRd+0asP1awWjz9/06dFkrILCXMIfQLo0D8rqmppn
65
+ * EfDDAwuudCpM9kcDmBRAm9JsKbQ6gzZWjkc5+QWSaQofojIHbjvj3xzguaCJn+oQ
66
+ * vHWM+hsAnaOgEwCyeZ3xqs+/5lwSbkE/tqJW98cEZGygBUVo9jxZRZx6KOfjpdrb
67
+ * yenO9LJr/qtyrZB31WJbqxI0m0AKTAO8UwIBAg==
71
68
  * -----END DH PARAMETERS-----
72
69
  */
73
- static unsigned char 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
70
+ static unsigned char dh2048_p[] = {
71
+ 0x8E, 0x68, 0x75, 0xB9, 0x01, 0xDD, 0x4D, 0xFC, 0x4E, 0xCB,
72
+ 0x11, 0x1B, 0x28, 0x05, 0x77, 0xD1, 0xF5, 0x1F, 0xCE, 0xA3,
73
+ 0x03, 0x17, 0xF0, 0xA1, 0x3F, 0x38, 0xDF, 0xCB, 0x39, 0x76,
74
+ 0x8D, 0xCA, 0xEA, 0x40, 0xC8, 0x6B, 0x93, 0xBE, 0xA8, 0xD8,
75
+ 0xD3, 0xCD, 0x5E, 0xAC, 0x47, 0xC2, 0xC7, 0x5D, 0x31, 0x9D,
76
+ 0x51, 0xCE, 0xF5, 0x3C, 0xFE, 0x39, 0x7E, 0xBA, 0x14, 0x6E,
77
+ 0x3D, 0x68, 0xD7, 0x08, 0x56, 0x5B, 0x84, 0x44, 0xF8, 0x37,
78
+ 0x5B, 0xEB, 0xBE, 0x26, 0x4C, 0xDD, 0x52, 0x61, 0x57, 0xC3,
79
+ 0xCF, 0x1E, 0xE8, 0x95, 0x38, 0x00, 0x8E, 0xCB, 0x7D, 0xA3,
80
+ 0x15, 0xDF, 0x92, 0xCF, 0x1E, 0x1B, 0xA3, 0x67, 0x17, 0x48,
81
+ 0xAF, 0x37, 0x84, 0x9E, 0xA3, 0x45, 0xDF, 0xB4, 0x6A, 0xC3,
82
+ 0xF5, 0x6B, 0x05, 0xA3, 0xCF, 0xDF, 0xF4, 0xE9, 0xD1, 0x64,
83
+ 0xAC, 0x82, 0xC2, 0x5C, 0xC2, 0x1F, 0x40, 0xBA, 0x34, 0x0F,
84
+ 0xCA, 0xEA, 0x9A, 0x9A, 0x67, 0x11, 0xF0, 0xC3, 0x03, 0x0B,
85
+ 0xAE, 0x74, 0x2A, 0x4C, 0xF6, 0x47, 0x03, 0x98, 0x14, 0x40,
86
+ 0x9B, 0xD2, 0x6C, 0x29, 0xB4, 0x3A, 0x83, 0x36, 0x56, 0x8E,
87
+ 0x47, 0x39, 0xF9, 0x05, 0x92, 0x69, 0x0A, 0x1F, 0xA2, 0x32,
88
+ 0x07, 0x6E, 0x3B, 0xE3, 0xDF, 0x1C, 0xE0, 0xB9, 0xA0, 0x89,
89
+ 0x9F, 0xEA, 0x10, 0xBC, 0x75, 0x8C, 0xFA, 0x1B, 0x00, 0x9D,
90
+ 0xA3, 0xA0, 0x13, 0x00, 0xB2, 0x79, 0x9D, 0xF1, 0xAA, 0xCF,
91
+ 0xBF, 0xE6, 0x5C, 0x12, 0x6E, 0x41, 0x3F, 0xB6, 0xA2, 0x56,
92
+ 0xF7, 0xC7, 0x04, 0x64, 0x6C, 0xA0, 0x05, 0x45, 0x68, 0xF6,
93
+ 0x3C, 0x59, 0x45, 0x9C, 0x7A, 0x28, 0xE7, 0xE3, 0xA5, 0xDA,
94
+ 0xDB, 0xC9, 0xE9, 0xCE, 0xF4, 0xB2, 0x6B, 0xFE, 0xAB, 0x72,
95
+ 0xAD, 0x90, 0x77, 0xD5, 0x62, 0x5B, 0xAB, 0x12, 0x34, 0x9B,
96
+ 0x40, 0x0A, 0x4C, 0x03, 0xBC, 0x53
85
97
  };
86
- static unsigned char dh1024_g[] = { 0x02 };
98
+ static unsigned char dh2048_g[] = { 0x02 };
87
99
 
88
100
  DH *dh;
101
+ #if !(OPENSSL_VERSION_NUMBER < 0x10100005L)
102
+ BIGNUM *p, *g;
103
+ #endif
104
+
89
105
  dh = DH_new();
90
106
 
91
- #if OPENSSL_VERSION_NUMBER < 0x10100005L || 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);
107
+ #if OPENSSL_VERSION_NUMBER < 0x10100005L
108
+ dh->p = BN_bin2bn(dh2048_p, sizeof(dh2048_p), NULL);
109
+ dh->g = BN_bin2bn(dh2048_g, sizeof(dh2048_g), NULL);
94
110
 
95
111
  if ((dh->p == NULL) || (dh->g == NULL)) {
96
112
  DH_free(dh);
97
113
  return NULL;
98
114
  }
99
115
  #else
100
- BIGNUM *p, *g;
101
- p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
102
- g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
116
+ p = BN_bin2bn(dh2048_p, sizeof(dh2048_p), NULL);
117
+ g = BN_bin2bn(dh2048_g, sizeof(dh2048_g), NULL);
103
118
 
104
119
  if (p == NULL || g == NULL || !DH_set0_pqg(dh, p, NULL, g)) {
105
120
  DH_free(dh);
@@ -111,6 +126,38 @@ DH *get_dh1024() {
111
126
 
112
127
  return dh;
113
128
  }
129
+ #endif
130
+
131
+ static void
132
+ sslctx_free(void *ptr) {
133
+ SSL_CTX *ctx = ptr;
134
+ SSL_CTX_free(ctx);
135
+ }
136
+
137
+ static const rb_data_type_t sslctx_type = {
138
+ "MiniSSL/SSLContext",
139
+ {
140
+ 0, sslctx_free,
141
+ },
142
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
143
+ };
144
+
145
+ ms_conn* engine_alloc(VALUE klass, VALUE* obj) {
146
+ ms_conn* conn;
147
+
148
+ *obj = TypedData_Make_Struct(klass, ms_conn, &engine_data_type, conn);
149
+
150
+ conn->read = BIO_new(BIO_s_mem());
151
+ BIO_set_nbio(conn->read, 1);
152
+
153
+ conn->write = BIO_new(BIO_s_mem());
154
+ BIO_set_nbio(conn->write, 1);
155
+
156
+ conn->ssl = 0;
157
+ conn->ctx = 0;
158
+
159
+ return conn;
160
+ }
114
161
 
115
162
  static int engine_verify_callback(int preverify_ok, X509_STORE_CTX* ctx) {
116
163
  X509* err_cert;
@@ -138,52 +185,118 @@ static int engine_verify_callback(int preverify_ok, X509_STORE_CTX* ctx) {
138
185
  return preverify_ok;
139
186
  }
140
187
 
141
- VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) {
142
- VALUE obj;
188
+ static VALUE
189
+ sslctx_alloc(VALUE klass) {
190
+ SSL_CTX *ctx;
191
+ long mode = 0 |
192
+ SSL_MODE_ENABLE_PARTIAL_WRITE |
193
+ SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
194
+ SSL_MODE_RELEASE_BUFFERS;
195
+
196
+ #ifdef HAVE_TLS_SERVER_METHOD
197
+ ctx = SSL_CTX_new(TLS_method());
198
+ // printf("\nctx using TLS_method security_level %d\n", SSL_CTX_get_security_level(ctx));
199
+ #else
200
+ ctx = SSL_CTX_new(SSLv23_method());
201
+ #endif
202
+ if (!ctx) {
203
+ rb_raise(eError, "SSL_CTX_new");
204
+ }
205
+ SSL_CTX_set_mode(ctx, mode);
206
+
207
+ return TypedData_Wrap_Struct(klass, &sslctx_type, ctx);
208
+ }
209
+
210
+ VALUE
211
+ sslctx_initialize(VALUE self, VALUE mini_ssl_ctx) {
143
212
  SSL_CTX* ctx;
144
- SSL* ssl;
145
- int min, ssl_options;
146
213
 
147
- ms_conn* conn = engine_alloc(self, &obj);
214
+ #ifdef HAVE_SSL_CTX_SET_MIN_PROTO_VERSION
215
+ int min;
216
+ #endif
217
+ int ssl_options;
218
+ VALUE key, cert, ca, verify_mode, ssl_cipher_filter, no_tlsv1, no_tlsv1_1,
219
+ verification_flags, session_id_bytes, cert_pem, key_pem;
220
+ #ifndef HAVE_SSL_CTX_SET_DH_AUTO
221
+ DH *dh;
222
+ #endif
223
+ BIO *bio;
224
+ X509 *x509;
225
+ EVP_PKEY *pkey;
148
226
 
149
- ID sym_key = rb_intern("key");
150
- VALUE key = rb_funcall(mini_ssl_ctx, sym_key, 0);
227
+ #if OPENSSL_VERSION_NUMBER < 0x10002000L
228
+ EC_KEY *ecdh;
229
+ #endif
151
230
 
152
- StringValue(key);
231
+ TypedData_Get_Struct(self, SSL_CTX, &sslctx_type, ctx);
153
232
 
154
- ID sym_cert = rb_intern("cert");
155
- VALUE cert = rb_funcall(mini_ssl_ctx, sym_cert, 0);
233
+ key = rb_funcall(mini_ssl_ctx, rb_intern_const("key"), 0);
156
234
 
157
- StringValue(cert);
235
+ cert = rb_funcall(mini_ssl_ctx, rb_intern_const("cert"), 0);
158
236
 
159
- ID sym_ca = rb_intern("ca");
160
- VALUE ca = rb_funcall(mini_ssl_ctx, sym_ca, 0);
237
+ ca = rb_funcall(mini_ssl_ctx, rb_intern_const("ca"), 0);
161
238
 
162
- ID sym_verify_mode = rb_intern("verify_mode");
163
- VALUE verify_mode = rb_funcall(mini_ssl_ctx, sym_verify_mode, 0);
239
+ cert_pem = rb_funcall(mini_ssl_ctx, rb_intern_const("cert_pem"), 0);
164
240
 
165
- 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);
241
+ key_pem = rb_funcall(mini_ssl_ctx, rb_intern_const("key_pem"), 0);
167
242
 
168
- ID sym_no_tlsv1 = rb_intern("no_tlsv1");
169
- VALUE no_tlsv1 = rb_funcall(mini_ssl_ctx, sym_no_tlsv1, 0);
243
+ verify_mode = rb_funcall(mini_ssl_ctx, rb_intern_const("verify_mode"), 0);
170
244
 
171
- 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);
245
+ ssl_cipher_filter = rb_funcall(mini_ssl_ctx, rb_intern_const("ssl_cipher_filter"), 0);
173
246
 
174
- #ifdef HAVE_TLS_SERVER_METHOD
175
- ctx = SSL_CTX_new(TLS_server_method());
176
- #else
177
- ctx = SSL_CTX_new(SSLv23_server_method());
178
- #endif
179
- conn->ctx = ctx;
247
+ no_tlsv1 = rb_funcall(mini_ssl_ctx, rb_intern_const("no_tlsv1"), 0);
248
+
249
+ no_tlsv1_1 = rb_funcall(mini_ssl_ctx, rb_intern_const("no_tlsv1_1"), 0);
250
+
251
+ if (!NIL_P(cert)) {
252
+ StringValue(cert);
253
+
254
+ if (SSL_CTX_use_certificate_chain_file(ctx, RSTRING_PTR(cert)) != 1) {
255
+ raise_file_error("SSL_CTX_use_certificate_chain_file", RSTRING_PTR(cert));
256
+ }
257
+ }
258
+
259
+ if (!NIL_P(key)) {
260
+ StringValue(key);
180
261
 
181
- SSL_CTX_use_certificate_chain_file(ctx, RSTRING_PTR(cert));
182
- SSL_CTX_use_PrivateKey_file(ctx, RSTRING_PTR(key), SSL_FILETYPE_PEM);
262
+ if (SSL_CTX_use_PrivateKey_file(ctx, RSTRING_PTR(key), SSL_FILETYPE_PEM) != 1) {
263
+ raise_file_error("SSL_CTX_use_PrivateKey_file", RSTRING_PTR(key));
264
+ }
265
+ }
266
+
267
+ if (!NIL_P(cert_pem)) {
268
+ bio = BIO_new(BIO_s_mem());
269
+ BIO_puts(bio, RSTRING_PTR(cert_pem));
270
+ x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
271
+
272
+ if (SSL_CTX_use_certificate(ctx, x509) != 1) {
273
+ raise_file_error("SSL_CTX_use_certificate", RSTRING_PTR(cert_pem));
274
+ }
275
+ }
276
+
277
+ if (!NIL_P(key_pem)) {
278
+ bio = BIO_new(BIO_s_mem());
279
+ BIO_puts(bio, RSTRING_PTR(key_pem));
280
+ pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
281
+
282
+ if (SSL_CTX_use_PrivateKey(ctx, pkey) != 1) {
283
+ raise_file_error("SSL_CTX_use_PrivateKey", RSTRING_PTR(key_pem));
284
+ }
285
+ }
286
+
287
+ verification_flags = rb_funcall(mini_ssl_ctx, rb_intern_const("verification_flags"), 0);
288
+
289
+ if (!NIL_P(verification_flags)) {
290
+ X509_VERIFY_PARAM *param = SSL_CTX_get0_param(ctx);
291
+ X509_VERIFY_PARAM_set_flags(param, NUM2INT(verification_flags));
292
+ SSL_CTX_set1_param(ctx, param);
293
+ }
183
294
 
184
295
  if (!NIL_P(ca)) {
185
296
  StringValue(ca);
186
- SSL_CTX_load_verify_locations(ctx, RSTRING_PTR(ca), NULL);
297
+ if (SSL_CTX_load_verify_locations(ctx, RSTRING_PTR(ca), NULL) != 1) {
298
+ raise_file_error("SSL_CTX_load_verify_locations", RSTRING_PTR(ca));
299
+ }
187
300
  }
188
301
 
189
302
  ssl_options = SSL_OP_CIPHER_SERVER_PREFERENCE | SSL_OP_SINGLE_ECDH_USE | SSL_OP_NO_COMPRESSION;
@@ -198,7 +311,7 @@ VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) {
198
311
  else {
199
312
  min = TLS1_VERSION;
200
313
  }
201
-
314
+
202
315
  SSL_CTX_set_min_proto_version(ctx, min);
203
316
 
204
317
  SSL_CTX_set_options(ctx, ssl_options);
@@ -226,35 +339,66 @@ VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) {
226
339
  SSL_CTX_set_cipher_list(ctx, "HIGH:!aNULL@STRENGTH");
227
340
  }
228
341
 
229
- DH *dh = get_dh1024();
230
- SSL_CTX_set_tmp_dh(ctx, dh);
231
-
232
342
  #if OPENSSL_VERSION_NUMBER < 0x10002000L
233
343
  // Remove this case if OpenSSL 1.0.1 (now EOL) support is no
234
344
  // longer needed.
235
- EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
345
+ ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
236
346
  if (ecdh) {
237
347
  SSL_CTX_set_tmp_ecdh(ctx, ecdh);
238
348
  EC_KEY_free(ecdh);
239
349
  }
240
350
  #elif OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
241
- // Prior to OpenSSL 1.1.0, servers must manually enable server-side ECDH
242
- // negotiation.
243
351
  SSL_CTX_set_ecdh_auto(ctx, 1);
244
352
  #endif
245
353
 
246
- ssl = SSL_new(ctx);
247
- conn->ssl = ssl;
248
- SSL_set_app_data(ssl, NULL);
249
-
250
354
  if (NIL_P(verify_mode)) {
251
- /* SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL); */
355
+ /* SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); */
252
356
  } else {
253
- SSL_set_verify(ssl, NUM2INT(verify_mode), engine_verify_callback);
357
+ SSL_CTX_set_verify(ctx, NUM2INT(verify_mode), engine_verify_callback);
254
358
  }
255
359
 
256
- SSL_set_bio(ssl, conn->read, conn->write);
360
+ // Random.bytes available in Ruby 2.5 and later, Random::DEFAULT deprecated in 3.0
361
+ session_id_bytes = rb_funcall(
362
+ #ifdef HAVE_RANDOM_BYTES
363
+ rb_cRandom,
364
+ #else
365
+ rb_const_get(rb_cRandom, rb_intern_const("DEFAULT")),
366
+ #endif
367
+ rb_intern_const("bytes"),
368
+ 1, ULL2NUM(SSL_MAX_SSL_SESSION_ID_LENGTH));
369
+
370
+ SSL_CTX_set_session_id_context(ctx,
371
+ (unsigned char *) RSTRING_PTR(session_id_bytes),
372
+ SSL_MAX_SSL_SESSION_ID_LENGTH);
373
+
374
+ // printf("\ninitialize end security_level %d\n", SSL_CTX_get_security_level(ctx));
375
+
376
+ #ifdef HAVE_SSL_CTX_SET_DH_AUTO
377
+ // https://www.openssl.org/docs/man3.0/man3/SSL_CTX_set_dh_auto.html
378
+ SSL_CTX_set_dh_auto(ctx, 1);
379
+ #else
380
+ dh = get_dh2048();
381
+ SSL_CTX_set_tmp_dh(ctx, dh);
382
+ #endif
383
+
384
+ rb_obj_freeze(self);
385
+ return self;
386
+ }
257
387
 
388
+ VALUE engine_init_server(VALUE self, VALUE sslctx) {
389
+ ms_conn* conn;
390
+ VALUE obj;
391
+ SSL_CTX* ctx;
392
+ SSL* ssl;
393
+
394
+ conn = engine_alloc(self, &obj);
395
+
396
+ TypedData_Get_Struct(sslctx, SSL_CTX, &sslctx_type, ctx);
397
+
398
+ ssl = SSL_new(ctx);
399
+ conn->ssl = ssl;
400
+ SSL_set_app_data(ssl, NULL);
401
+ SSL_set_bio(ssl, conn->read, conn->write);
258
402
  SSL_set_accept_state(ssl);
259
403
  return obj;
260
404
  }
@@ -281,7 +425,7 @@ VALUE engine_inject(VALUE self, VALUE str) {
281
425
  ms_conn* conn;
282
426
  long used;
283
427
 
284
- Data_Get_Struct(self, ms_conn, conn);
428
+ TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
285
429
 
286
430
  StringValue(str);
287
431
 
@@ -294,13 +438,14 @@ VALUE engine_inject(VALUE self, VALUE str) {
294
438
  return INT2FIX(used);
295
439
  }
296
440
 
297
- static VALUE eError;
441
+ NORETURN(void raise_error(SSL* ssl, int result));
298
442
 
299
443
  void raise_error(SSL* ssl, int result) {
300
444
  char buf[512];
301
445
  char msg[512];
302
446
  const char* err_str;
303
447
  int err = errno;
448
+ int mask = 4095;
304
449
  int ssl_err = SSL_get_error(ssl, result);
305
450
  int verify_err = (int) SSL_get_verify_result(ssl);
306
451
 
@@ -317,8 +462,7 @@ void raise_error(SSL* ssl, int result) {
317
462
  } else {
318
463
  err = (int) ERR_get_error();
319
464
  ERR_error_string_n(err, buf, sizeof(buf));
320
- snprintf(msg, sizeof(msg), "OpenSSL error: %s - %d", buf, err);
321
-
465
+ snprintf(msg, sizeof(msg), "OpenSSL error: %s - %d", buf, err & mask);
322
466
  }
323
467
  } else {
324
468
  snprintf(msg, sizeof(msg), "Unknown OpenSSL error: %d", ssl_err);
@@ -333,7 +477,7 @@ VALUE engine_read(VALUE self) {
333
477
  char buf[512];
334
478
  int bytes, error;
335
479
 
336
- Data_Get_Struct(self, ms_conn, conn);
480
+ TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
337
481
 
338
482
  ERR_clear_error();
339
483
 
@@ -360,7 +504,7 @@ VALUE engine_write(VALUE self, VALUE str) {
360
504
  ms_conn* conn;
361
505
  int bytes;
362
506
 
363
- Data_Get_Struct(self, ms_conn, conn);
507
+ TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
364
508
 
365
509
  StringValue(str);
366
510
 
@@ -382,9 +526,11 @@ VALUE engine_extract(VALUE self) {
382
526
  ms_conn* conn;
383
527
  int bytes;
384
528
  size_t pending;
385
- char buf[512];
529
+ // https://www.openssl.org/docs/manmaster/man3/BIO_f_buffer.html
530
+ // crypto/bio/bf_buff.c DEFAULT_BUFFER_SIZE
531
+ char buf[4096];
386
532
 
387
- Data_Get_Struct(self, ms_conn, conn);
533
+ TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
388
534
 
389
535
  pending = BIO_pending(conn->write);
390
536
  if(pending > 0) {
@@ -403,7 +549,7 @@ VALUE engine_shutdown(VALUE self) {
403
549
  ms_conn* conn;
404
550
  int ok;
405
551
 
406
- Data_Get_Struct(self, ms_conn, conn);
552
+ TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
407
553
 
408
554
  ERR_clear_error();
409
555
 
@@ -418,7 +564,7 @@ VALUE engine_shutdown(VALUE self) {
418
564
  VALUE engine_init(VALUE self) {
419
565
  ms_conn* conn;
420
566
 
421
- Data_Get_Struct(self, ms_conn, conn);
567
+ TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
422
568
 
423
569
  return SSL_in_init(conn->ssl) ? Qtrue : Qfalse;
424
570
  }
@@ -431,9 +577,13 @@ VALUE engine_peercert(VALUE self) {
431
577
  ms_cert_buf* cert_buf = NULL;
432
578
  VALUE rb_cert_buf;
433
579
 
434
- Data_Get_Struct(self, ms_conn, conn);
580
+ TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
435
581
 
582
+ #ifdef HAVE_SSL_GET1_PEER_CERTIFICATE
583
+ cert = SSL_get1_peer_certificate(conn->ssl);
584
+ #else
436
585
  cert = SSL_get_peer_certificate(conn->ssl);
586
+ #endif
437
587
  if(!cert) {
438
588
  /*
439
589
  * See if there was a failed certificate associated with this client.
@@ -462,12 +612,22 @@ VALUE engine_peercert(VALUE self) {
462
612
  return rb_cert_buf;
463
613
  }
464
614
 
615
+ /* @see Puma::MiniSSL::Socket#ssl_version_state
616
+ * @version 5.0.0
617
+ */
618
+ static VALUE
619
+ engine_ssl_vers_st(VALUE self) {
620
+ ms_conn* conn;
621
+ TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
622
+ return rb_ary_new3(2, rb_str_new2(SSL_get_version(conn->ssl)), rb_str_new2(SSL_state_string(conn->ssl)));
623
+ }
624
+
465
625
  VALUE noop(VALUE self) {
466
626
  return Qnil;
467
627
  }
468
628
 
469
629
  void Init_mini_ssl(VALUE puma) {
470
- VALUE mod, eng;
630
+ VALUE mod, eng, sslctx;
471
631
 
472
632
  /* Fake operation for documentation (RDoc, YARD) */
473
633
  #if 0 == 1
@@ -480,7 +640,15 @@ void Init_mini_ssl(VALUE puma) {
480
640
  ERR_load_crypto_strings();
481
641
 
482
642
  mod = rb_define_module_under(puma, "MiniSSL");
643
+
483
644
  eng = rb_define_class_under(mod, "Engine", rb_cObject);
645
+ rb_undef_alloc_func(eng);
646
+
647
+ sslctx = rb_define_class_under(mod, "SSLContext", rb_cObject);
648
+ rb_define_alloc_func(sslctx, sslctx_alloc);
649
+ rb_define_method(sslctx, "initialize", sslctx_initialize, 1);
650
+ rb_undef_method(sslctx, "initialize_copy");
651
+
484
652
 
485
653
  // OpenSSL Build / Runtime/Load versions
486
654
 
@@ -493,27 +661,27 @@ void Init_mini_ssl(VALUE puma) {
493
661
  #else
494
662
  rb_define_const(mod, "OPENSSL_LIBRARY_VERSION", rb_str_new2(SSLeay_version(SSLEAY_VERSION)));
495
663
  #endif
496
-
497
- #if defined(OPENSSL_NO_SSL3) || defined(OPENSSL_NO_SSL3_METHOD)
498
- /* True if SSL3 is not available */
499
- rb_define_const(mod, "OPENSSL_NO_SSL3", Qtrue);
500
- #else
501
- rb_define_const(mod, "OPENSSL_NO_SSL3", Qfalse);
502
- #endif
503
-
504
- #if defined(OPENSSL_NO_TLS1) || defined(OPENSSL_NO_TLS1_METHOD)
505
- /* True if TLS1 is not available */
506
- rb_define_const(mod, "OPENSSL_NO_TLS1", Qtrue);
507
- #else
508
- rb_define_const(mod, "OPENSSL_NO_TLS1", Qfalse);
509
- #endif
510
-
511
- #if defined(OPENSSL_NO_TLS1_1) || defined(OPENSSL_NO_TLS1_1_METHOD)
512
- /* True if TLS1_1 is not available */
513
- rb_define_const(mod, "OPENSSL_NO_TLS1_1", Qtrue);
514
- #else
515
- rb_define_const(mod, "OPENSSL_NO_TLS1_1", Qfalse);
516
- #endif
664
+
665
+ #if defined(OPENSSL_NO_SSL3) || defined(OPENSSL_NO_SSL3_METHOD)
666
+ /* True if SSL3 is not available */
667
+ rb_define_const(mod, "OPENSSL_NO_SSL3", Qtrue);
668
+ #else
669
+ rb_define_const(mod, "OPENSSL_NO_SSL3", Qfalse);
670
+ #endif
671
+
672
+ #if defined(OPENSSL_NO_TLS1) || defined(OPENSSL_NO_TLS1_METHOD)
673
+ /* True if TLS1 is not available */
674
+ rb_define_const(mod, "OPENSSL_NO_TLS1", Qtrue);
675
+ #else
676
+ rb_define_const(mod, "OPENSSL_NO_TLS1", Qfalse);
677
+ #endif
678
+
679
+ #if defined(OPENSSL_NO_TLS1_1) || defined(OPENSSL_NO_TLS1_1_METHOD)
680
+ /* True if TLS1_1 is not available */
681
+ rb_define_const(mod, "OPENSSL_NO_TLS1_1", Qtrue);
682
+ #else
683
+ rb_define_const(mod, "OPENSSL_NO_TLS1_1", Qfalse);
684
+ #endif
517
685
 
518
686
  rb_define_singleton_method(mod, "check", noop, 0);
519
687
 
@@ -533,13 +701,16 @@ void Init_mini_ssl(VALUE puma) {
533
701
  rb_define_method(eng, "init?", engine_init, 0);
534
702
 
535
703
  rb_define_method(eng, "peercert", engine_peercert, 0);
704
+
705
+ rb_define_method(eng, "ssl_vers_st", engine_ssl_vers_st, 0);
536
706
  }
537
707
 
538
708
  #else
539
709
 
710
+ NORETURN(VALUE raise_error(VALUE self));
711
+
540
712
  VALUE raise_error(VALUE self) {
541
713
  rb_raise(rb_eStandardError, "SSL not available in this build");
542
- return Qnil;
543
714
  }
544
715
 
545
716
  void Init_mini_ssl(VALUE puma) {
@@ -0,0 +1,15 @@
1
+ package puma;
2
+
3
+ import java.io.IOException;
4
+
5
+ import org.jruby.Ruby;
6
+ import org.jruby.runtime.load.BasicLibraryService;
7
+
8
+ import org.jruby.puma.Http11;
9
+
10
+ public class PumaHttp11Service implements BasicLibraryService {
11
+ public boolean basicLoad(final Ruby runtime) throws IOException {
12
+ Http11.createHttp11(runtime);
13
+ return true;
14
+ }
15
+ }
@@ -30,8 +30,8 @@ public class Http11 extends RubyObject {
30
30
  public final static String MAX_REQUEST_URI_LENGTH_ERR = "HTTP element REQUEST_URI is longer than the 12288 allowed length.";
31
31
  public final static int MAX_FRAGMENT_LENGTH = 1024;
32
32
  public final static String MAX_FRAGMENT_LENGTH_ERR = "HTTP element REQUEST_PATH is longer than the 1024 allowed length.";
33
- public final static int MAX_REQUEST_PATH_LENGTH = 2048;
34
- public final static String MAX_REQUEST_PATH_LENGTH_ERR = "HTTP element REQUEST_PATH is longer than the 2048 allowed length.";
33
+ public final static int MAX_REQUEST_PATH_LENGTH = 8192;
34
+ public final static String MAX_REQUEST_PATH_LENGTH_ERR = "HTTP element REQUEST_PATH is longer than the 8192 allowed length.";
35
35
  public final static int MAX_QUERY_STRING_LENGTH = 1024 * 10;
36
36
  public final static String MAX_QUERY_STRING_LENGTH_ERR = "HTTP element QUERY_STRING is longer than the 10240 allowed length.";
37
37
  public final static int MAX_HEADER_LENGTH = 1024 * (80 + 32);
@@ -99,6 +99,8 @@ public class Http11 extends RubyObject {
99
99
  int bite = b.get(i) & 0xFF;
100
100
  if(bite == '-') {
101
101
  b.set(i, (byte)'_');
102
+ } else if(bite == '_') {
103
+ b.set(i, (byte)',');
102
104
  } else {
103
105
  b.set(i, (byte)Character.toUpperCase(bite));
104
106
  }
@@ -197,7 +199,7 @@ public class Http11 extends RubyObject {
197
199
  validateMaxLength(runtime, parser.nread,MAX_HEADER_LENGTH, MAX_HEADER_LENGTH_ERR);
198
200
 
199
201
  if(hp.has_error()) {
200
- throw newHTTPParserError(runtime, "Invalid HTTP format, parsing fails.");
202
+ throw newHTTPParserError(runtime, "Invalid HTTP format, parsing fails. Are you trying to open an SSL connection to a non-SSL Puma?");
201
203
  } else {
202
204
  return runtime.newFixnum(parser.nread);
203
205
  }