puma 4.3.12 → 6.0.2

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 (90) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +1618 -521
  3. data/LICENSE +23 -20
  4. data/README.md +130 -42
  5. data/bin/puma-wild +3 -9
  6. data/docs/architecture.md +63 -26
  7. data/docs/compile_options.md +55 -0
  8. data/docs/deployment.md +60 -69
  9. data/docs/fork_worker.md +31 -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/{tools → docs}/jungle/rc.d/puma.conf +0 -0
  14. data/docs/kubernetes.md +66 -0
  15. data/docs/nginx.md +2 -2
  16. data/docs/plugins.md +15 -15
  17. data/docs/rails_dev_mode.md +28 -0
  18. data/docs/restart.md +46 -23
  19. data/docs/signals.md +13 -11
  20. data/docs/stats.md +142 -0
  21. data/docs/systemd.md +85 -128
  22. data/docs/testing_benchmarks_local_files.md +150 -0
  23. data/docs/testing_test_rackup_ci_files.md +36 -0
  24. data/ext/puma_http11/PumaHttp11Service.java +2 -4
  25. data/ext/puma_http11/ext_help.h +1 -1
  26. data/ext/puma_http11/extconf.rb +49 -12
  27. data/ext/puma_http11/http11_parser.c +46 -48
  28. data/ext/puma_http11/http11_parser.h +2 -2
  29. data/ext/puma_http11/http11_parser.java.rl +3 -3
  30. data/ext/puma_http11/http11_parser.rl +3 -3
  31. data/ext/puma_http11/http11_parser_common.rl +2 -2
  32. data/ext/puma_http11/mini_ssl.c +250 -93
  33. data/ext/puma_http11/no_ssl/PumaHttp11Service.java +15 -0
  34. data/ext/puma_http11/org/jruby/puma/Http11.java +6 -6
  35. data/ext/puma_http11/org/jruby/puma/Http11Parser.java +4 -6
  36. data/ext/puma_http11/org/jruby/puma/MiniSSL.java +241 -96
  37. data/ext/puma_http11/puma_http11.c +46 -57
  38. data/lib/puma/app/status.rb +52 -38
  39. data/lib/puma/binder.rb +232 -119
  40. data/lib/puma/cli.rb +33 -33
  41. data/lib/puma/client.rb +129 -88
  42. data/lib/puma/cluster/worker.rb +175 -0
  43. data/lib/puma/cluster/worker_handle.rb +97 -0
  44. data/lib/puma/cluster.rb +224 -231
  45. data/lib/puma/commonlogger.rb +2 -2
  46. data/lib/puma/configuration.rb +112 -87
  47. data/lib/puma/const.rb +86 -91
  48. data/lib/puma/control_cli.rb +99 -79
  49. data/lib/puma/detect.rb +31 -2
  50. data/lib/puma/dsl.rb +426 -110
  51. data/lib/puma/error_logger.rb +112 -0
  52. data/lib/puma/events.rb +16 -115
  53. data/lib/puma/io_buffer.rb +44 -2
  54. data/lib/puma/jruby_restart.rb +2 -59
  55. data/lib/puma/json_serialization.rb +96 -0
  56. data/lib/puma/launcher/bundle_pruner.rb +104 -0
  57. data/lib/puma/launcher.rb +170 -148
  58. data/lib/puma/log_writer.rb +137 -0
  59. data/lib/puma/minissl/context_builder.rb +35 -19
  60. data/lib/puma/minissl.rb +213 -55
  61. data/lib/puma/null_io.rb +18 -1
  62. data/lib/puma/plugin/tmp_restart.rb +1 -1
  63. data/lib/puma/plugin.rb +3 -12
  64. data/lib/puma/rack/builder.rb +5 -9
  65. data/lib/puma/rack_default.rb +1 -1
  66. data/lib/puma/reactor.rb +85 -369
  67. data/lib/puma/request.rb +644 -0
  68. data/lib/puma/runner.rb +86 -76
  69. data/lib/puma/server.rb +306 -793
  70. data/lib/puma/single.rb +18 -74
  71. data/lib/puma/state_file.rb +45 -8
  72. data/lib/puma/systemd.rb +47 -0
  73. data/lib/puma/thread_pool.rb +136 -68
  74. data/lib/puma/util.rb +21 -4
  75. data/lib/puma.rb +54 -7
  76. data/lib/rack/handler/puma.rb +11 -12
  77. data/tools/{docker/Dockerfile → Dockerfile} +1 -1
  78. metadata +31 -23
  79. data/docs/tcp_mode.md +0 -96
  80. data/ext/puma_http11/io_buffer.c +0 -155
  81. data/ext/puma_http11/org/jruby/puma/IOBuffer.java +0 -72
  82. data/lib/puma/accept_nonblock.rb +0 -29
  83. data/lib/puma/tcp_logger.rb +0 -41
  84. data/tools/jungle/README.md +0 -19
  85. data/tools/jungle/init.d/README.md +0 -61
  86. data/tools/jungle/init.d/puma +0 -421
  87. data/tools/jungle/init.d/run-puma +0 -18
  88. data/tools/jungle/upstart/README.md +0 -61
  89. data/tools/jungle/upstart/puma-manager.conf +0 -31
  90. data/tools/jungle/upstart/puma.conf +0 -69
@@ -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,23 +49,13 @@ 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
 
58
+ #ifndef HAVE_SSL_CTX_SET_DH_AUTO
65
59
  DH *get_dh2048(void) {
66
60
  /* `openssl dhparam -C 2048`
67
61
  * -----BEGIN DH PARAMETERS-----
@@ -104,13 +98,13 @@ DH *get_dh2048(void) {
104
98
  static unsigned char dh2048_g[] = { 0x02 };
105
99
 
106
100
  DH *dh;
107
- #if !(OPENSSL_VERSION_NUMBER < 0x10100005L || defined(LIBRESSL_VERSION_NUMBER))
101
+ #if !(OPENSSL_VERSION_NUMBER < 0x10100005L)
108
102
  BIGNUM *p, *g;
109
103
  #endif
110
104
 
111
105
  dh = DH_new();
112
106
 
113
- #if OPENSSL_VERSION_NUMBER < 0x10100005L || defined(LIBRESSL_VERSION_NUMBER)
107
+ #if OPENSSL_VERSION_NUMBER < 0x10100005L
114
108
  dh->p = BN_bin2bn(dh2048_p, sizeof(dh2048_p), NULL);
115
109
  dh->g = BN_bin2bn(dh2048_g, sizeof(dh2048_g), NULL);
116
110
 
@@ -132,6 +126,38 @@ DH *get_dh2048(void) {
132
126
 
133
127
  return dh;
134
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
+ }
135
161
 
136
162
  static int engine_verify_callback(int preverify_ok, X509_STORE_CTX* ctx) {
137
163
  X509* err_cert;
@@ -159,52 +185,129 @@ static int engine_verify_callback(int preverify_ok, X509_STORE_CTX* ctx) {
159
185
  return preverify_ok;
160
186
  }
161
187
 
162
- VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) {
163
- VALUE obj, session_id_bytes;
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) {
164
212
  SSL_CTX* ctx;
165
- SSL* ssl;
166
- int min, ssl_options;
213
+ int ssl_options;
214
+ VALUE key, cert, ca, verify_mode, ssl_cipher_filter, no_tlsv1, no_tlsv1_1,
215
+ verification_flags, session_id_bytes, cert_pem, key_pem;
216
+ BIO *bio;
217
+ X509 *x509;
218
+ EVP_PKEY *pkey;
219
+ #ifdef HAVE_SSL_CTX_SET_MIN_PROTO_VERSION
220
+ int min;
221
+ #endif
222
+ #ifndef HAVE_SSL_CTX_SET_DH_AUTO
223
+ DH *dh;
224
+ #endif
225
+ #if OPENSSL_VERSION_NUMBER < 0x10002000L
226
+ EC_KEY *ecdh;
227
+ #endif
228
+ #ifdef HAVE_SSL_CTX_SET_SESSION_CACHE_MODE
229
+ VALUE reuse, reuse_cache_size, reuse_timeout;
167
230
 
168
- ms_conn* conn = engine_alloc(self, &obj);
231
+ reuse = rb_funcall(mini_ssl_ctx, rb_intern_const("reuse"), 0);
232
+ reuse_cache_size = rb_funcall(mini_ssl_ctx, rb_intern_const("reuse_cache_size"), 0);
233
+ reuse_timeout = rb_funcall(mini_ssl_ctx, rb_intern_const("reuse_timeout"), 0);
234
+ #endif
169
235
 
170
- ID sym_key = rb_intern("key");
171
- VALUE key = rb_funcall(mini_ssl_ctx, sym_key, 0);
236
+ key = rb_funcall(mini_ssl_ctx, rb_intern_const("key"), 0);
172
237
 
173
- StringValue(key);
238
+ cert = rb_funcall(mini_ssl_ctx, rb_intern_const("cert"), 0);
174
239
 
175
- ID sym_cert = rb_intern("cert");
176
- VALUE cert = rb_funcall(mini_ssl_ctx, sym_cert, 0);
240
+ ca = rb_funcall(mini_ssl_ctx, rb_intern_const("ca"), 0);
177
241
 
178
- StringValue(cert);
242
+ cert_pem = rb_funcall(mini_ssl_ctx, rb_intern_const("cert_pem"), 0);
179
243
 
180
- ID sym_ca = rb_intern("ca");
181
- VALUE ca = rb_funcall(mini_ssl_ctx, sym_ca, 0);
244
+ key_pem = rb_funcall(mini_ssl_ctx, rb_intern_const("key_pem"), 0);
182
245
 
183
- ID sym_verify_mode = rb_intern("verify_mode");
184
- VALUE verify_mode = rb_funcall(mini_ssl_ctx, sym_verify_mode, 0);
246
+ verify_mode = rb_funcall(mini_ssl_ctx, rb_intern_const("verify_mode"), 0);
185
247
 
186
- ID sym_ssl_cipher_filter = rb_intern("ssl_cipher_filter");
187
- VALUE ssl_cipher_filter = rb_funcall(mini_ssl_ctx, sym_ssl_cipher_filter, 0);
248
+ ssl_cipher_filter = rb_funcall(mini_ssl_ctx, rb_intern_const("ssl_cipher_filter"), 0);
188
249
 
189
- ID sym_no_tlsv1 = rb_intern("no_tlsv1");
190
- VALUE no_tlsv1 = rb_funcall(mini_ssl_ctx, sym_no_tlsv1, 0);
250
+ no_tlsv1 = rb_funcall(mini_ssl_ctx, rb_intern_const("no_tlsv1"), 0);
191
251
 
192
- ID sym_no_tlsv1_1 = rb_intern("no_tlsv1_1");
193
- VALUE no_tlsv1_1 = rb_funcall(mini_ssl_ctx, sym_no_tlsv1_1, 0);
252
+ no_tlsv1_1 = rb_funcall(mini_ssl_ctx, rb_intern_const("no_tlsv1_1"), 0);
194
253
 
195
- #ifdef HAVE_TLS_SERVER_METHOD
196
- ctx = SSL_CTX_new(TLS_server_method());
197
- #else
198
- ctx = SSL_CTX_new(SSLv23_server_method());
199
- #endif
200
- conn->ctx = ctx;
254
+ TypedData_Get_Struct(self, SSL_CTX, &sslctx_type, ctx);
201
255
 
202
- SSL_CTX_use_certificate_chain_file(ctx, RSTRING_PTR(cert));
203
- SSL_CTX_use_PrivateKey_file(ctx, RSTRING_PTR(key), SSL_FILETYPE_PEM);
256
+ if (!NIL_P(cert)) {
257
+ StringValue(cert);
258
+
259
+ if (SSL_CTX_use_certificate_chain_file(ctx, RSTRING_PTR(cert)) != 1) {
260
+ raise_file_error("SSL_CTX_use_certificate_chain_file", RSTRING_PTR(cert));
261
+ }
262
+ }
263
+
264
+ if (!NIL_P(key)) {
265
+ StringValue(key);
266
+
267
+ if (SSL_CTX_use_PrivateKey_file(ctx, RSTRING_PTR(key), SSL_FILETYPE_PEM) != 1) {
268
+ raise_file_error("SSL_CTX_use_PrivateKey_file", RSTRING_PTR(key));
269
+ }
270
+ }
271
+
272
+ if (!NIL_P(cert_pem)) {
273
+ bio = BIO_new(BIO_s_mem());
274
+ BIO_puts(bio, RSTRING_PTR(cert_pem));
275
+ x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
276
+
277
+ if (SSL_CTX_use_certificate(ctx, x509) != 1) {
278
+ BIO_free(bio);
279
+ raise_file_error("SSL_CTX_use_certificate", RSTRING_PTR(cert_pem));
280
+ }
281
+ X509_free(x509);
282
+ BIO_free(bio);
283
+ }
284
+
285
+ if (!NIL_P(key_pem)) {
286
+ bio = BIO_new(BIO_s_mem());
287
+ BIO_puts(bio, RSTRING_PTR(key_pem));
288
+ pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
289
+
290
+ if (SSL_CTX_use_PrivateKey(ctx, pkey) != 1) {
291
+ BIO_free(bio);
292
+ raise_file_error("SSL_CTX_use_PrivateKey", RSTRING_PTR(key_pem));
293
+ }
294
+ EVP_PKEY_free(pkey);
295
+ BIO_free(bio);
296
+ }
297
+
298
+ verification_flags = rb_funcall(mini_ssl_ctx, rb_intern_const("verification_flags"), 0);
299
+
300
+ if (!NIL_P(verification_flags)) {
301
+ X509_VERIFY_PARAM *param = SSL_CTX_get0_param(ctx);
302
+ X509_VERIFY_PARAM_set_flags(param, NUM2INT(verification_flags));
303
+ SSL_CTX_set1_param(ctx, param);
304
+ }
204
305
 
205
306
  if (!NIL_P(ca)) {
206
307
  StringValue(ca);
207
- SSL_CTX_load_verify_locations(ctx, RSTRING_PTR(ca), NULL);
308
+ if (SSL_CTX_load_verify_locations(ctx, RSTRING_PTR(ca), NULL) != 1) {
309
+ raise_file_error("SSL_CTX_load_verify_locations", RSTRING_PTR(ca));
310
+ }
208
311
  }
209
312
 
210
313
  ssl_options = SSL_OP_CIPHER_SERVER_PREFERENCE | SSL_OP_SINGLE_ECDH_USE | SSL_OP_NO_COMPRESSION;
@@ -222,8 +325,6 @@ VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) {
222
325
 
223
326
  SSL_CTX_set_min_proto_version(ctx, min);
224
327
 
225
- SSL_CTX_set_options(ctx, ssl_options);
226
-
227
328
  #else
228
329
  /* As of 1.0.2f, SSL_OP_SINGLE_DH_USE key use is always on */
229
330
  ssl_options |= SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_SINGLE_DH_USE;
@@ -234,10 +335,23 @@ VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) {
234
335
  if(RTEST(no_tlsv1_1)) {
235
336
  ssl_options |= SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1;
236
337
  }
237
- SSL_CTX_set_options(ctx, ssl_options);
238
338
  #endif
239
339
 
240
- SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
340
+ #ifdef HAVE_SSL_CTX_SET_SESSION_CACHE_MODE
341
+ if (!NIL_P(reuse)) {
342
+ SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER);
343
+ if (!NIL_P(reuse_cache_size)) {
344
+ SSL_CTX_sess_set_cache_size(ctx, NUM2INT(reuse_cache_size));
345
+ }
346
+ if (!NIL_P(reuse_timeout)) {
347
+ SSL_CTX_set_timeout(ctx, NUM2INT(reuse_timeout));
348
+ }
349
+ } else {
350
+ SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
351
+ }
352
+ #endif
353
+
354
+ SSL_CTX_set_options(ctx, ssl_options);
241
355
 
242
356
  if (!NIL_P(ssl_cipher_filter)) {
243
357
  StringValue(ssl_cipher_filter);
@@ -247,6 +361,23 @@ VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) {
247
361
  SSL_CTX_set_cipher_list(ctx, "HIGH:!aNULL@STRENGTH");
248
362
  }
249
363
 
364
+ #if OPENSSL_VERSION_NUMBER < 0x10002000L
365
+ // Remove this case if OpenSSL 1.0.1 (now EOL) support is no longer needed.
366
+ ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
367
+ if (ecdh) {
368
+ SSL_CTX_set_tmp_ecdh(ctx, ecdh);
369
+ EC_KEY_free(ecdh);
370
+ }
371
+ #elif OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
372
+ SSL_CTX_set_ecdh_auto(ctx, 1);
373
+ #endif
374
+
375
+ if (NIL_P(verify_mode)) {
376
+ /* SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); */
377
+ } else {
378
+ SSL_CTX_set_verify(ctx, NUM2INT(verify_mode), engine_verify_callback);
379
+ }
380
+
250
381
  // Random.bytes available in Ruby 2.5 and later, Random::DEFAULT deprecated in 3.0
251
382
  session_id_bytes = rb_funcall(
252
383
  #ifdef HAVE_RANDOM_BYTES
@@ -261,35 +392,34 @@ VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) {
261
392
  (unsigned char *) RSTRING_PTR(session_id_bytes),
262
393
  SSL_MAX_SSL_SESSION_ID_LENGTH);
263
394
 
264
- DH *dh = get_dh2048();
265
- SSL_CTX_set_tmp_dh(ctx, dh);
395
+ // printf("\ninitialize end security_level %d\n", SSL_CTX_get_security_level(ctx));
266
396
 
267
- #if OPENSSL_VERSION_NUMBER < 0x10002000L
268
- // Remove this case if OpenSSL 1.0.1 (now EOL) support is no
269
- // longer needed.
270
- EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
271
- if (ecdh) {
272
- SSL_CTX_set_tmp_ecdh(ctx, ecdh);
273
- EC_KEY_free(ecdh);
274
- }
275
- #elif OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
276
- // Prior to OpenSSL 1.1.0, servers must manually enable server-side ECDH
277
- // negotiation.
278
- SSL_CTX_set_ecdh_auto(ctx, 1);
397
+ #ifdef HAVE_SSL_CTX_SET_DH_AUTO
398
+ // https://www.openssl.org/docs/man3.0/man3/SSL_CTX_set_dh_auto.html
399
+ SSL_CTX_set_dh_auto(ctx, 1);
400
+ #else
401
+ dh = get_dh2048();
402
+ SSL_CTX_set_tmp_dh(ctx, dh);
279
403
  #endif
280
404
 
405
+ rb_obj_freeze(self);
406
+ return self;
407
+ }
408
+
409
+ VALUE engine_init_server(VALUE self, VALUE sslctx) {
410
+ ms_conn* conn;
411
+ VALUE obj;
412
+ SSL_CTX* ctx;
413
+ SSL* ssl;
414
+
415
+ conn = engine_alloc(self, &obj);
416
+
417
+ TypedData_Get_Struct(sslctx, SSL_CTX, &sslctx_type, ctx);
418
+
281
419
  ssl = SSL_new(ctx);
282
420
  conn->ssl = ssl;
283
421
  SSL_set_app_data(ssl, NULL);
284
-
285
- if (NIL_P(verify_mode)) {
286
- /* SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL); */
287
- } else {
288
- SSL_set_verify(ssl, NUM2INT(verify_mode), engine_verify_callback);
289
- }
290
-
291
422
  SSL_set_bio(ssl, conn->read, conn->write);
292
-
293
423
  SSL_set_accept_state(ssl);
294
424
  return obj;
295
425
  }
@@ -316,7 +446,7 @@ VALUE engine_inject(VALUE self, VALUE str) {
316
446
  ms_conn* conn;
317
447
  long used;
318
448
 
319
- Data_Get_Struct(self, ms_conn, conn);
449
+ TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
320
450
 
321
451
  StringValue(str);
322
452
 
@@ -329,13 +459,14 @@ VALUE engine_inject(VALUE self, VALUE str) {
329
459
  return INT2FIX(used);
330
460
  }
331
461
 
332
- static VALUE eError;
462
+ NORETURN(void raise_error(SSL* ssl, int result));
333
463
 
334
464
  void raise_error(SSL* ssl, int result) {
335
465
  char buf[512];
336
466
  char msg[512];
337
467
  const char* err_str;
338
468
  int err = errno;
469
+ int mask = 4095;
339
470
  int ssl_err = SSL_get_error(ssl, result);
340
471
  int verify_err = (int) SSL_get_verify_result(ssl);
341
472
 
@@ -352,8 +483,7 @@ void raise_error(SSL* ssl, int result) {
352
483
  } else {
353
484
  err = (int) ERR_get_error();
354
485
  ERR_error_string_n(err, buf, sizeof(buf));
355
- snprintf(msg, sizeof(msg), "OpenSSL error: %s - %d", buf, err);
356
-
486
+ snprintf(msg, sizeof(msg), "OpenSSL error: %s - %d", buf, err & mask);
357
487
  }
358
488
  } else {
359
489
  snprintf(msg, sizeof(msg), "Unknown OpenSSL error: %d", ssl_err);
@@ -368,7 +498,7 @@ VALUE engine_read(VALUE self) {
368
498
  char buf[512];
369
499
  int bytes, error;
370
500
 
371
- Data_Get_Struct(self, ms_conn, conn);
501
+ TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
372
502
 
373
503
  ERR_clear_error();
374
504
 
@@ -395,7 +525,7 @@ VALUE engine_write(VALUE self, VALUE str) {
395
525
  ms_conn* conn;
396
526
  int bytes;
397
527
 
398
- Data_Get_Struct(self, ms_conn, conn);
528
+ TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
399
529
 
400
530
  StringValue(str);
401
531
 
@@ -417,9 +547,11 @@ VALUE engine_extract(VALUE self) {
417
547
  ms_conn* conn;
418
548
  int bytes;
419
549
  size_t pending;
420
- char buf[512];
550
+ // https://www.openssl.org/docs/manmaster/man3/BIO_f_buffer.html
551
+ // crypto/bio/bf_buff.c DEFAULT_BUFFER_SIZE
552
+ char buf[4096];
421
553
 
422
- Data_Get_Struct(self, ms_conn, conn);
554
+ TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
423
555
 
424
556
  pending = BIO_pending(conn->write);
425
557
  if(pending > 0) {
@@ -438,7 +570,7 @@ VALUE engine_shutdown(VALUE self) {
438
570
  ms_conn* conn;
439
571
  int ok;
440
572
 
441
- Data_Get_Struct(self, ms_conn, conn);
573
+ TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
442
574
 
443
575
  ERR_clear_error();
444
576
 
@@ -453,7 +585,7 @@ VALUE engine_shutdown(VALUE self) {
453
585
  VALUE engine_init(VALUE self) {
454
586
  ms_conn* conn;
455
587
 
456
- Data_Get_Struct(self, ms_conn, conn);
588
+ TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
457
589
 
458
590
  return SSL_in_init(conn->ssl) ? Qtrue : Qfalse;
459
591
  }
@@ -466,9 +598,13 @@ VALUE engine_peercert(VALUE self) {
466
598
  ms_cert_buf* cert_buf = NULL;
467
599
  VALUE rb_cert_buf;
468
600
 
469
- Data_Get_Struct(self, ms_conn, conn);
601
+ TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
470
602
 
603
+ #ifdef HAVE_SSL_GET1_PEER_CERTIFICATE
604
+ cert = SSL_get1_peer_certificate(conn->ssl);
605
+ #else
471
606
  cert = SSL_get_peer_certificate(conn->ssl);
607
+ #endif
472
608
  if(!cert) {
473
609
  /*
474
610
  * See if there was a failed certificate associated with this client.
@@ -497,12 +633,22 @@ VALUE engine_peercert(VALUE self) {
497
633
  return rb_cert_buf;
498
634
  }
499
635
 
636
+ /* @see Puma::MiniSSL::Socket#ssl_version_state
637
+ * @version 5.0.0
638
+ */
639
+ static VALUE
640
+ engine_ssl_vers_st(VALUE self) {
641
+ ms_conn* conn;
642
+ TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
643
+ return rb_ary_new3(2, rb_str_new2(SSL_get_version(conn->ssl)), rb_str_new2(SSL_state_string(conn->ssl)));
644
+ }
645
+
500
646
  VALUE noop(VALUE self) {
501
647
  return Qnil;
502
648
  }
503
649
 
504
650
  void Init_mini_ssl(VALUE puma) {
505
- VALUE mod, eng;
651
+ VALUE mod, eng, sslctx;
506
652
 
507
653
  /* Fake operation for documentation (RDoc, YARD) */
508
654
  #if 0 == 1
@@ -515,7 +661,15 @@ void Init_mini_ssl(VALUE puma) {
515
661
  ERR_load_crypto_strings();
516
662
 
517
663
  mod = rb_define_module_under(puma, "MiniSSL");
664
+
518
665
  eng = rb_define_class_under(mod, "Engine", rb_cObject);
666
+ rb_undef_alloc_func(eng);
667
+
668
+ sslctx = rb_define_class_under(mod, "SSLContext", rb_cObject);
669
+ rb_define_alloc_func(sslctx, sslctx_alloc);
670
+ rb_define_method(sslctx, "initialize", sslctx_initialize, 1);
671
+ rb_undef_method(sslctx, "initialize_copy");
672
+
519
673
 
520
674
  // OpenSSL Build / Runtime/Load versions
521
675
 
@@ -568,13 +722,16 @@ void Init_mini_ssl(VALUE puma) {
568
722
  rb_define_method(eng, "init?", engine_init, 0);
569
723
 
570
724
  rb_define_method(eng, "peercert", engine_peercert, 0);
725
+
726
+ rb_define_method(eng, "ssl_vers_st", engine_ssl_vers_st, 0);
571
727
  }
572
728
 
573
729
  #else
574
730
 
731
+ NORETURN(VALUE raise_error(VALUE self));
732
+
575
733
  VALUE raise_error(VALUE self) {
576
734
  rb_raise(rb_eStandardError, "SSL not available in this build");
577
- return Qnil;
578
735
  }
579
736
 
580
737
  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);
@@ -46,7 +46,7 @@ public class Http11 extends RubyObject {
46
46
  public static final ByteList FRAGMENT_BYTELIST = new ByteList(ByteList.plain("FRAGMENT"));
47
47
  public static final ByteList REQUEST_PATH_BYTELIST = new ByteList(ByteList.plain("REQUEST_PATH"));
48
48
  public static final ByteList QUERY_STRING_BYTELIST = new ByteList(ByteList.plain("QUERY_STRING"));
49
- public static final ByteList HTTP_VERSION_BYTELIST = new ByteList(ByteList.plain("HTTP_VERSION"));
49
+ public static final ByteList SERVER_PROTOCOL_BYTELIST = new ByteList(ByteList.plain("SERVER_PROTOCOL"));
50
50
 
51
51
  private static ObjectAllocator ALLOCATOR = new ObjectAllocator() {
52
52
  public IRubyObject allocate(Ruby runtime, RubyClass klass) {
@@ -153,9 +153,9 @@ public class Http11 extends RubyObject {
153
153
  req.fastASet(RubyString.newStringShared(runtime, QUERY_STRING_BYTELIST),val);
154
154
  }
155
155
 
156
- public static void http_version(Ruby runtime, RubyHash req, ByteList buffer, int at, int length) {
156
+ public static void server_protocol(Ruby runtime, RubyHash req, ByteList buffer, int at, int length) {
157
157
  RubyString val = RubyString.newString(runtime,new ByteList(buffer,at,length));
158
- req.fastASet(RubyString.newStringShared(runtime, HTTP_VERSION_BYTELIST),val);
158
+ req.fastASet(RubyString.newStringShared(runtime, SERVER_PROTOCOL_BYTELIST),val);
159
159
  }
160
160
 
161
161
  public void header_done(Ruby runtime, RubyHash req, ByteList buffer, int at, int length) {
@@ -197,7 +197,7 @@ public class Http11 extends RubyObject {
197
197
  validateMaxLength(runtime, parser.nread,MAX_HEADER_LENGTH, MAX_HEADER_LENGTH_ERR);
198
198
 
199
199
  if(hp.has_error()) {
200
- throw newHTTPParserError(runtime, "Invalid HTTP format, parsing fails.");
200
+ throw newHTTPParserError(runtime, "Invalid HTTP format, parsing fails. Are you trying to open an SSL connection to a non-SSL Puma?");
201
201
  } else {
202
202
  return runtime.newFixnum(parser.nread);
203
203
  }
@@ -184,8 +184,6 @@ static final int puma_parser_start = 1;
184
184
  static final int puma_parser_first_final = 46;
185
185
  static final int puma_parser_error = 0;
186
186
 
187
- static final int puma_parser_en_main = 1;
188
-
189
187
 
190
188
  // line 62 "ext/puma_http11/http11_parser.java.rl"
191
189
 
@@ -214,7 +212,7 @@ static final int puma_parser_en_main = 1;
214
212
  cs = 0;
215
213
 
216
214
 
217
- // line 218 "ext/puma_http11/org/jruby/puma/Http11Parser.java"
215
+ // line 216 "ext/puma_http11/org/jruby/puma/Http11Parser.java"
218
216
  {
219
217
  cs = puma_parser_start;
220
218
  }
@@ -246,7 +244,7 @@ static final int puma_parser_en_main = 1;
246
244
  parser.buffer = buffer;
247
245
 
248
246
 
249
- // line 250 "ext/puma_http11/org/jruby/puma/Http11Parser.java"
247
+ // line 248 "ext/puma_http11/org/jruby/puma/Http11Parser.java"
250
248
  {
251
249
  int _klen;
252
250
  int _trans = 0;
@@ -385,7 +383,7 @@ case 1:
385
383
  case 11:
386
384
  // line 42 "ext/puma_http11/http11_parser.java.rl"
387
385
  {
388
- Http11.http_version(runtime, parser.data, parser.buffer, parser.mark, p-parser.mark);
386
+ Http11.server_protocol(runtime, parser.data, parser.buffer, parser.mark, p-parser.mark);
389
387
  }
390
388
  break;
391
389
  case 12:
@@ -402,7 +400,7 @@ case 1:
402
400
  { p += 1; _goto_targ = 5; if (true) continue _goto;}
403
401
  }
404
402
  break;
405
- // line 406 "ext/puma_http11/org/jruby/puma/Http11Parser.java"
403
+ // line 404 "ext/puma_http11/org/jruby/puma/Http11Parser.java"
406
404
  }
407
405
  }
408
406
  }