puma 5.6.4 → 5.6.8

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 (80) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +63 -3
  3. data/LICENSE +0 -0
  4. data/README.md +0 -0
  5. data/bin/puma-wild +0 -0
  6. data/docs/architecture.md +0 -0
  7. data/docs/compile_options.md +0 -0
  8. data/docs/deployment.md +0 -0
  9. data/docs/fork_worker.md +0 -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 +0 -0
  14. data/docs/jungle/rc.d/README.md +0 -0
  15. data/docs/jungle/rc.d/puma.conf +0 -0
  16. data/docs/kubernetes.md +0 -0
  17. data/docs/nginx.md +0 -0
  18. data/docs/plugins.md +0 -0
  19. data/docs/rails_dev_mode.md +0 -0
  20. data/docs/restart.md +0 -0
  21. data/docs/signals.md +0 -0
  22. data/docs/stats.md +0 -0
  23. data/docs/systemd.md +0 -0
  24. data/ext/puma_http11/PumaHttp11Service.java +0 -0
  25. data/ext/puma_http11/ext_help.h +0 -0
  26. data/ext/puma_http11/extconf.rb +8 -3
  27. data/ext/puma_http11/http11_parser.c +0 -0
  28. data/ext/puma_http11/http11_parser.h +0 -0
  29. data/ext/puma_http11/http11_parser.java.rl +0 -0
  30. data/ext/puma_http11/http11_parser.rl +0 -0
  31. data/ext/puma_http11/http11_parser_common.rl +0 -0
  32. data/ext/puma_http11/mini_ssl.c +28 -10
  33. data/ext/puma_http11/no_ssl/PumaHttp11Service.java +0 -0
  34. data/ext/puma_http11/org/jruby/puma/Http11.java +0 -0
  35. data/ext/puma_http11/org/jruby/puma/Http11Parser.java +0 -0
  36. data/ext/puma_http11/org/jruby/puma/MiniSSL.java +10 -12
  37. data/ext/puma_http11/puma_http11.c +0 -0
  38. data/lib/puma/app/status.rb +3 -0
  39. data/lib/puma/binder.rb +1 -1
  40. data/lib/puma/cli.rb +0 -0
  41. data/lib/puma/client.rb +42 -8
  42. data/lib/puma/cluster/worker.rb +0 -0
  43. data/lib/puma/cluster/worker_handle.rb +0 -0
  44. data/lib/puma/cluster.rb +0 -0
  45. data/lib/puma/commonlogger.rb +0 -0
  46. data/lib/puma/configuration.rb +0 -0
  47. data/lib/puma/const.rb +1 -1
  48. data/lib/puma/control_cli.rb +18 -12
  49. data/lib/puma/detect.rb +0 -0
  50. data/lib/puma/dsl.rb +6 -2
  51. data/lib/puma/error_logger.rb +0 -0
  52. data/lib/puma/events.rb +0 -0
  53. data/lib/puma/io_buffer.rb +0 -0
  54. data/lib/puma/jruby_restart.rb +0 -0
  55. data/lib/puma/json_serialization.rb +0 -0
  56. data/lib/puma/launcher.rb +11 -0
  57. data/lib/puma/minissl/context_builder.rb +0 -0
  58. data/lib/puma/minissl.rb +9 -4
  59. data/lib/puma/null_io.rb +5 -0
  60. data/lib/puma/plugin/tmp_restart.rb +0 -0
  61. data/lib/puma/plugin.rb +0 -0
  62. data/lib/puma/queue_close.rb +0 -0
  63. data/lib/puma/rack/builder.rb +0 -0
  64. data/lib/puma/rack/urlmap.rb +0 -0
  65. data/lib/puma/rack_default.rb +0 -0
  66. data/lib/puma/reactor.rb +0 -0
  67. data/lib/puma/request.rb +5 -1
  68. data/lib/puma/runner.rb +0 -0
  69. data/lib/puma/server.rb +2 -0
  70. data/lib/puma/single.rb +0 -0
  71. data/lib/puma/state_file.rb +1 -0
  72. data/lib/puma/systemd.rb +0 -0
  73. data/lib/puma/thread_pool.rb +0 -0
  74. data/lib/puma/util.rb +12 -3
  75. data/lib/puma.rb +5 -3
  76. data/lib/rack/handler/puma.rb +0 -0
  77. data/lib/rack/version_restriction.rb +15 -0
  78. data/tools/Dockerfile +0 -0
  79. data/tools/trickletest.rb +0 -0
  80. metadata +4 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ff9f4c8b81e1bfced36da8ecfe60912bd6bb37a2f989f2f8489d31cbe1a5947a
4
- data.tar.gz: 6821bc93adc639fea1ed82559b0e67c70bfd86fa0b0ec641eed65e020fb53440
3
+ metadata.gz: cc34dc2b7094b86d3eec5100455de02cdcfb14a2e382059565e06e512d5c40ac
4
+ data.tar.gz: 10080424606d3a4613f1b27b33199a048711da57e4b45a55f7e997346c64c419
5
5
  SHA512:
6
- metadata.gz: 7b3eafbc651e03214851f79a89cb92637f7966f7d645446e15ac29e118d3b564aa28222ef54c1ea02f946da813172cf24bf9fb3b4c9d9b14dc1dadbc20754579
7
- data.tar.gz: 760c958a8c56ee5ec7b2208e5d1d9e0ef31c09975d058cd535f42382895f76f0854a18c68f671b37736e1588a372bc752a676cbbd1a896a08bd97962642dc0b7
6
+ metadata.gz: 18da16eff3311151ff29f868f07762d509541b1302dd6ff80bf323bb6fdd73da9d8bc32983a37b71e439faf4753e8110bdafb8f444df205b62f742376c980147
7
+ data.tar.gz: 89968813be0e066fc4de68dc439827d621d2d1803c58c64ee2df78f4d9baa4785fc7865d655990564ff52d9cd64ebc8d9dbc4be048334e0f8db954d83efaeef1
data/History.md CHANGED
@@ -1,3 +1,36 @@
1
+ ## 5.6.8 / 2023-01-08
2
+
3
+ * Security
4
+ * Limit the size of chunk extensions. Without this limit, an attacker could cause unbounded resource (CPU, network bandwidth) consumption. ([GHSA-c2f4-cvqm-65w2](https://github.com/puma/puma/security/advisories/GHSA-c2f4-cvqm-65w2))
5
+
6
+ ## 5.6.7 / 2023-08-18
7
+
8
+ * Security
9
+ * Address HTTP request smuggling vulnerabilities with zero-length Content Length header and trailer fields ([GHSA-68xg-gqqm-vgj8](https://github.com/puma/puma/security/advisories/GHSA-68xg-gqqm-vgj8))
10
+
11
+ ## 5.6.6 / 2023-06-21
12
+
13
+ * Bugfix
14
+ * Allow Puma to be loaded with Rack 3 ([#3166])
15
+
16
+ ## 5.6.5 / 2022-08-23
17
+
18
+ * Feature
19
+ * Puma::ControlCLI - allow refork command to be sent as a request ([#2868], [#2866])
20
+
21
+ * Bugfixes
22
+ * NullIO#closed should return false ([#2883])
23
+ * [jruby] Fix TLS verification hang ([#2890], [#2729])
24
+ * extconf.rb - don't use pkg_config('openssl') if '--with-openssl-dir' is used ([#2885], [#2839])
25
+ * MiniSSL - detect SSL_CTX_set_dh_auto ([#2864], [#2863])
26
+ * Fix rack.after_reply exceptions breaking connections ([#2861], [#2856])
27
+ * Escape SSL cert and filenames ([#2855])
28
+ * Fail hard if SSL certs or keys are invalid ([#2848])
29
+ * Fail hard if SSL certs or keys cannot be read by user ([#2847])
30
+ * Fix build with Opaque DH in LibreSSL 3.5. ([#2838])
31
+ * Pre-existing socket file removed when TERM is issued after USR2 (if puma is running in cluster mode) ([#2817])
32
+ * Fix Puma::StateFile#load incompatibility ([#2810])
33
+
1
34
  ## 5.6.4 / 2022-03-30
2
35
 
3
36
  * Security
@@ -1845,6 +1878,33 @@ be added back in a future date when a java Puma::MiniSSL is added.
1845
1878
  * Bugfixes
1846
1879
  * Your bugfix goes here <Most recent on the top, like GitHub> (#Github Number)
1847
1880
 
1881
+ [#3166]:https://github.com/puma/puma/issues/3166 "Issue by @JoeDupuis, merged 2023-06-08"
1882
+ [#2883]:https://github.com/puma/puma/pull/2883 "PR by @MSP-Greg, merged 2022-06-02"
1883
+ [#2868]:https://github.com/puma/puma/pull/2868 "PR by @MSP-Greg, merged 2022-06-02"
1884
+ [#2866]:https://github.com/puma/puma/issues/2866 "Issue by @slondr, closed 2022-06-02"
1885
+ [#2888]:https://github.com/puma/puma/pull/2888 "PR by @MSP-Greg, merged 2022-06-01"
1886
+ [#2890]:https://github.com/puma/puma/pull/2890 "PR by @kares, merged 2022-06-01"
1887
+ [#2729]:https://github.com/puma/puma/issues/2729 "Issue by @kares, closed 2022-06-01"
1888
+ [#2885]:https://github.com/puma/puma/pull/2885 "PR by @MSP-Greg, merged 2022-05-30"
1889
+ [#2839]:https://github.com/puma/puma/issues/2839 "Issue by @wlipa, closed 2022-05-30"
1890
+ [#2882]:https://github.com/puma/puma/pull/2882 "PR by @MSP-Greg, merged 2022-05-19"
1891
+ [#2864]:https://github.com/puma/puma/pull/2864 "PR by @MSP-Greg, merged 2022-04-26"
1892
+ [#2863]:https://github.com/puma/puma/issues/2863 "Issue by @eradman, closed 2022-04-26"
1893
+ [#2861]:https://github.com/puma/puma/pull/2861 "PR by @BlakeWilliams, merged 2022-04-17"
1894
+ [#2856]:https://github.com/puma/puma/issues/2856 "Issue by @nateberkopec, closed 2022-04-17"
1895
+ [#2855]:https://github.com/puma/puma/pull/2855 "PR by @stanhu, merged 2022-04-09"
1896
+ [#2848]:https://github.com/puma/puma/pull/2848 "PR by @stanhu, merged 2022-04-02"
1897
+ [#2847]:https://github.com/puma/puma/pull/2847 "PR by @stanhu, merged 2022-04-02"
1898
+ [#2838]:https://github.com/puma/puma/pull/2838 "PR by @epsilon-0, merged 2022-03-03"
1899
+ [#2817]:https://github.com/puma/puma/pull/2817 "PR by @khustochka, merged 2022-02-20"
1900
+ [#2810]:https://github.com/puma/puma/pull/2810 "PR by @kzkn, merged 2022-01-27"
1901
+ [#2899]:https://github.com/puma/puma/pull/2899 "PR by @kares, merged 2022-07-04"
1902
+ [#2891]:https://github.com/puma/puma/pull/2891 "PR by @gingerlime, merged 2022-06-02"
1903
+ [#2886]:https://github.com/puma/puma/pull/2886 "PR by @kares, merged 2022-05-30"
1904
+ [#2884]:https://github.com/puma/puma/pull/2884 "PR by @kares, merged 2022-05-30"
1905
+ [#2875]:https://github.com/puma/puma/pull/2875 "PR by @ylecuyer, merged 2022-05-19"
1906
+ [#2840]:https://github.com/puma/puma/pull/2840 "PR by @LukaszMaslej, merged 2022-04-13"
1907
+ [#2849]:https://github.com/puma/puma/pull/2849 "PR by @kares, merged 2022-04-09"
1848
1908
  [#2809]:https://github.com/puma/puma/pull/2809 "PR by @dentarg, merged 2022-01-26"
1849
1909
  [#2764]:https://github.com/puma/puma/pull/2764 "PR by @dentarg, merged 2022-01-18"
1850
1910
  [#2708]:https://github.com/puma/puma/issues/2708 "Issue by @erikaxel, closed 2022-01-18"
@@ -1930,7 +1990,7 @@ be added back in a future date when a java Puma::MiniSSL is added.
1930
1990
  [#2519]:https://github.com/puma/puma/pull/2519 "PR by @MSP-Greg, merged 2021-01-26"
1931
1991
  [#2522]:https://github.com/puma/puma/pull/2522 "PR by @jcmfernandes, merged 2021-01-12"
1932
1992
  [#2490]:https://github.com/puma/puma/pull/2490 "PR by @Bonias, merged 2020-12-07"
1933
- [#2486]:https://github.com/puma/puma/pull/2486 "PR by @ccverak, merged 2020-12-02"
1993
+ [#2486]:https://github.com/puma/puma/pull/2486 "PR by @karloscodes, merged 2020-12-02"
1934
1994
  [#2535]:https://github.com/puma/puma/pull/2535 "PR by @MSP-Greg, merged 2021-01-27"
1935
1995
  [#2529]:https://github.com/puma/puma/pull/2529 "PR by @MSP-Greg, merged 2021-01-24"
1936
1996
  [#2533]:https://github.com/puma/puma/pull/2533 "PR by @MSP-Greg, merged 2021-01-24"
@@ -1940,7 +2000,7 @@ be added back in a future date when a java Puma::MiniSSL is added.
1940
2000
  [#2521]:https://github.com/puma/puma/pull/2521 "PR by @ojab, merged 2021-01-04"
1941
2001
  [#2531]:https://github.com/puma/puma/pull/2531 "PR by @wjordan, merged 2021-01-19"
1942
2002
  [#2510]:https://github.com/puma/puma/pull/2510 "PR by @micke, merged 2020-12-10"
1943
- [#2472]:https://github.com/puma/puma/pull/2472 "PR by @ccverak, merged 2020-11-02"
2003
+ [#2472]:https://github.com/puma/puma/pull/2472 "PR by @karloscodes, merged 2020-11-02"
1944
2004
  [#2438]:https://github.com/puma/puma/pull/2438 "PR by @ekohl, merged 2020-10-26"
1945
2005
  [#2406]:https://github.com/puma/puma/pull/2406 "PR by @fdel15, merged 2020-10-19"
1946
2006
  [#2449]:https://github.com/puma/puma/pull/2449 "PR by @MSP-Greg, merged 2020-10-28"
@@ -2367,7 +2427,7 @@ be added back in a future date when a java Puma::MiniSSL is added.
2367
2427
  [#709]:https://github.com/puma/puma/pull/709 "PR by @lian, merged 2015-06-10"
2368
2428
  [#711]:https://github.com/puma/puma/pull/711 "PR by @julik, merged 2015-06-10"
2369
2429
  [#712]:https://github.com/puma/puma/pull/712 "PR by @chewi, merged 2015-07-14"
2370
- [#715]:https://github.com/puma/puma/pull/715 "PR by @0RaymondJiang0, merged 2015-07-14"
2430
+ [#715]:https://github.com/puma/puma/pull/715 "PR by @raymondmars, merged 2015-07-14"
2371
2431
  [#725]:https://github.com/puma/puma/pull/725 "PR by @rwz, merged 2015-07-14"
2372
2432
  [#726]:https://github.com/puma/puma/pull/726 "PR by @jshafton, merged 2015-07-14"
2373
2433
  [#729]:https://github.com/puma/puma/pull/729 "PR by @allaire, merged 2015-07-14"
data/LICENSE CHANGED
File without changes
data/README.md CHANGED
File without changes
data/bin/puma-wild CHANGED
File without changes
data/docs/architecture.md CHANGED
File without changes
File without changes
data/docs/deployment.md CHANGED
File without changes
data/docs/fork_worker.md CHANGED
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
data/docs/kubernetes.md CHANGED
File without changes
data/docs/nginx.md CHANGED
File without changes
data/docs/plugins.md CHANGED
File without changes
File without changes
data/docs/restart.md CHANGED
File without changes
data/docs/signals.md CHANGED
File without changes
data/docs/stats.md CHANGED
File without changes
data/docs/systemd.md CHANGED
File without changes
File without changes
File without changes
@@ -9,9 +9,11 @@ if $mingw && RUBY_VERSION >= '2.4'
9
9
  end
10
10
 
11
11
  unless ENV["DISABLE_SSL"]
12
- dir_config("openssl")
12
+ # don't use pkg_config('openssl') if '--with-openssl-dir' is used
13
+ has_openssl_dir = dir_config('openssl').any?
14
+ found_pkg_config = !has_openssl_dir && pkg_config('openssl')
13
15
 
14
- found_ssl = if (!$mingw || RUBY_VERSION >= '2.4') && (t = pkg_config 'openssl')
16
+ found_ssl = if (!$mingw || RUBY_VERSION >= '2.4') && found_pkg_config
15
17
  puts 'using OpenSSL pkgconfig (openssl.pc)'
16
18
  true
17
19
  elsif %w'crypto libeay32'.find {|crypto| have_library(crypto, 'BIO_read')} &&
@@ -35,7 +37,10 @@ unless ENV["DISABLE_SSL"]
35
37
  have_func "X509_STORE_up_ref"
36
38
  have_func "SSL_CTX_set_ecdh_auto(NULL, 0)" , "openssl/ssl.h"
37
39
 
38
- # below are yes for 3.0.0 & later, use for OpenSSL 3 detection
40
+ # below exists in 1.1.0 and later, but isn't documented until 3.0.0
41
+ have_func "SSL_CTX_set_dh_auto(NULL, 0)" , "openssl/ssl.h"
42
+
43
+ # below is yes for 3.0.0 & later
39
44
  have_func "SSL_get1_peer_certificate" , "openssl/ssl.h"
40
45
 
41
46
  # Random.bytes available in Ruby 2.5 and later, Random::DEFAULT deprecated in 3.0
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -30,6 +30,12 @@ typedef struct {
30
30
 
31
31
  VALUE eError;
32
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
+
33
39
  void engine_free(void *ptr) {
34
40
  ms_conn *conn = ptr;
35
41
  ms_cert_buf* cert_buf = (ms_cert_buf*)SSL_get_app_data(conn->ssl);
@@ -49,7 +55,7 @@ const rb_data_type_t engine_data_type = {
49
55
  0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
50
56
  };
51
57
 
52
- #ifndef HAVE_SSL_GET1_PEER_CERTIFICATE
58
+ #ifndef HAVE_SSL_CTX_SET_DH_AUTO
53
59
  DH *get_dh2048(void) {
54
60
  /* `openssl dhparam -C 2048`
55
61
  * -----BEGIN DH PARAMETERS-----
@@ -92,13 +98,13 @@ DH *get_dh2048(void) {
92
98
  static unsigned char dh2048_g[] = { 0x02 };
93
99
 
94
100
  DH *dh;
95
- #if !(OPENSSL_VERSION_NUMBER < 0x10100005L || defined(LIBRESSL_VERSION_NUMBER))
101
+ #if !(OPENSSL_VERSION_NUMBER < 0x10100005L)
96
102
  BIGNUM *p, *g;
97
103
  #endif
98
104
 
99
105
  dh = DH_new();
100
106
 
101
- #if OPENSSL_VERSION_NUMBER < 0x10100005L || defined(LIBRESSL_VERSION_NUMBER)
107
+ #if OPENSSL_VERSION_NUMBER < 0x10100005L
102
108
  dh->p = BN_bin2bn(dh2048_p, sizeof(dh2048_p), NULL);
103
109
  dh->g = BN_bin2bn(dh2048_g, sizeof(dh2048_g), NULL);
104
110
 
@@ -211,7 +217,7 @@ sslctx_initialize(VALUE self, VALUE mini_ssl_ctx) {
211
217
  int ssl_options;
212
218
  VALUE key, cert, ca, verify_mode, ssl_cipher_filter, no_tlsv1, no_tlsv1_1,
213
219
  verification_flags, session_id_bytes, cert_pem, key_pem;
214
- #ifndef HAVE_SSL_GET1_PEER_CERTIFICATE
220
+ #ifndef HAVE_SSL_CTX_SET_DH_AUTO
215
221
  DH *dh;
216
222
  #endif
217
223
  BIO *bio;
@@ -244,12 +250,18 @@ sslctx_initialize(VALUE self, VALUE mini_ssl_ctx) {
244
250
 
245
251
  if (!NIL_P(cert)) {
246
252
  StringValue(cert);
247
- SSL_CTX_use_certificate_chain_file(ctx, RSTRING_PTR(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
+ }
248
257
  }
249
258
 
250
259
  if (!NIL_P(key)) {
251
260
  StringValue(key);
252
- SSL_CTX_use_PrivateKey_file(ctx, RSTRING_PTR(key), SSL_FILETYPE_PEM);
261
+
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
+ }
253
265
  }
254
266
 
255
267
  if (!NIL_P(cert_pem)) {
@@ -257,7 +269,9 @@ sslctx_initialize(VALUE self, VALUE mini_ssl_ctx) {
257
269
  BIO_puts(bio, RSTRING_PTR(cert_pem));
258
270
  x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
259
271
 
260
- SSL_CTX_use_certificate(ctx, x509);
272
+ if (SSL_CTX_use_certificate(ctx, x509) != 1) {
273
+ raise_file_error("SSL_CTX_use_certificate", RSTRING_PTR(cert_pem));
274
+ }
261
275
  }
262
276
 
263
277
  if (!NIL_P(key_pem)) {
@@ -265,7 +279,9 @@ sslctx_initialize(VALUE self, VALUE mini_ssl_ctx) {
265
279
  BIO_puts(bio, RSTRING_PTR(key_pem));
266
280
  pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
267
281
 
268
- SSL_CTX_use_PrivateKey(ctx, pkey);
282
+ if (SSL_CTX_use_PrivateKey(ctx, pkey) != 1) {
283
+ raise_file_error("SSL_CTX_use_PrivateKey", RSTRING_PTR(key_pem));
284
+ }
269
285
  }
270
286
 
271
287
  verification_flags = rb_funcall(mini_ssl_ctx, rb_intern_const("verification_flags"), 0);
@@ -278,7 +294,9 @@ sslctx_initialize(VALUE self, VALUE mini_ssl_ctx) {
278
294
 
279
295
  if (!NIL_P(ca)) {
280
296
  StringValue(ca);
281
- 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
+ }
282
300
  }
283
301
 
284
302
  ssl_options = SSL_OP_CIPHER_SERVER_PREFERENCE | SSL_OP_SINGLE_ECDH_USE | SSL_OP_NO_COMPRESSION;
@@ -355,7 +373,7 @@ sslctx_initialize(VALUE self, VALUE mini_ssl_ctx) {
355
373
 
356
374
  // printf("\ninitialize end security_level %d\n", SSL_CTX_get_security_level(ctx));
357
375
 
358
- #ifdef HAVE_SSL_GET1_PEER_CERTIFICATE
376
+ #ifdef HAVE_SSL_CTX_SET_DH_AUTO
359
377
  // https://www.openssl.org/docs/man3.0/man3/SSL_CTX_set_dh_auto.html
360
378
  SSL_CTX_set_dh_auto(ctx, 1);
361
379
  #else
File without changes
File without changes
File without changes
@@ -279,14 +279,6 @@ public class MiniSSL extends RubyObject {
279
279
  }
280
280
  }
281
281
 
282
- // after each op, run any delegated tasks if needed
283
- if(res.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
284
- Runnable runnable;
285
- while ((runnable = engine.getDelegatedTask()) != null) {
286
- runnable.run();
287
- }
288
- }
289
-
290
282
  return res;
291
283
  }
292
284
 
@@ -304,11 +296,12 @@ public class MiniSSL extends RubyObject {
304
296
 
305
297
  HandshakeStatus handshakeStatus = engine.getHandshakeStatus();
306
298
  boolean done = false;
307
- SSLEngineResult res = null;
308
299
  while (!done) {
300
+ SSLEngineResult res;
309
301
  switch (handshakeStatus) {
310
302
  case NEED_WRAP:
311
303
  res = doOp(SSLOperation.WRAP, inboundAppData, outboundNetData);
304
+ handshakeStatus = res.getHandshakeStatus();
312
305
  break;
313
306
  case NEED_UNWRAP:
314
307
  res = doOp(SSLOperation.UNWRAP, inboundNetData, inboundAppData);
@@ -316,13 +309,18 @@ public class MiniSSL extends RubyObject {
316
309
  // need more data before we can shake more hands
317
310
  done = true;
318
311
  }
312
+ handshakeStatus = res.getHandshakeStatus();
313
+ break;
314
+ case NEED_TASK:
315
+ Runnable runnable;
316
+ while ((runnable = engine.getDelegatedTask()) != null) {
317
+ runnable.run();
318
+ }
319
+ handshakeStatus = engine.getHandshakeStatus();
319
320
  break;
320
321
  default:
321
322
  done = true;
322
323
  }
323
- if (!done) {
324
- handshakeStatus = res.getHandshakeStatus();
325
- }
326
324
  }
327
325
 
328
326
  if (inboundNetData.hasRemaining()) {
File without changes
@@ -39,6 +39,9 @@ module Puma
39
39
  when 'phased-restart'
40
40
  @launcher.phased_restart ? 200 : 404
41
41
 
42
+ when 'refork'
43
+ @launcher.refork ? 200 : 404
44
+
42
45
  when 'reload-worker-directory'
43
46
  @launcher.send(:reload_worker_directory) ? 200 : 404
44
47
 
data/lib/puma/binder.rb CHANGED
@@ -189,7 +189,7 @@ module Puma
189
189
  end
190
190
 
191
191
  if fd = @inherited_fds.delete(str)
192
- @unix_paths << path unless abstract
192
+ @unix_paths << path unless abstract || File.exist?(path)
193
193
  io = inherit_unix_listener path, fd
194
194
  logger.log "* Inherited #{str}"
195
195
  elsif sock = @activated_sockets.delete([ :unix, path ]) ||
data/lib/puma/cli.rb CHANGED
File without changes
data/lib/puma/client.rb CHANGED
@@ -45,7 +45,16 @@ module Puma
45
45
 
46
46
  # chunked body validation
47
47
  CHUNK_SIZE_INVALID = /[^\h]/.freeze
48
- CHUNK_VALID_ENDING = "\r\n".freeze
48
+ CHUNK_VALID_ENDING = Const::LINE_END
49
+ CHUNK_VALID_ENDING_SIZE = CHUNK_VALID_ENDING.bytesize
50
+
51
+ # The maximum number of bytes we'll buffer looking for a valid
52
+ # chunk header.
53
+ MAX_CHUNK_HEADER_SIZE = 4096
54
+
55
+ # The maximum amount of excess data the client sends
56
+ # using chunk size extensions before we abort the connection.
57
+ MAX_CHUNK_EXCESS = 16 * 1024
49
58
 
50
59
  # Content-Length header value validation
51
60
  CONTENT_LENGTH_VALUE_INVALID = /[^\d]/.freeze
@@ -347,8 +356,8 @@ module Puma
347
356
  cl = @env[CONTENT_LENGTH]
348
357
 
349
358
  if cl
350
- # cannot contain characters that are not \d
351
- if cl =~ CONTENT_LENGTH_VALUE_INVALID
359
+ # cannot contain characters that are not \d, or be empty
360
+ if cl =~ CONTENT_LENGTH_VALUE_INVALID || cl.empty?
352
361
  raise HttpParserError, "Invalid Content-Length: #{cl.inspect}"
353
362
  end
354
363
  else
@@ -459,6 +468,7 @@ module Puma
459
468
  @chunked_body = true
460
469
  @partial_part_left = 0
461
470
  @prev_chunk = ""
471
+ @excess_cr = 0
462
472
 
463
473
  @body = Tempfile.new(Const::PUMA_TMP_BASE)
464
474
  @body.unlink
@@ -509,7 +519,7 @@ module Puma
509
519
 
510
520
  while !io.eof?
511
521
  line = io.gets
512
- if line.end_with?("\r\n")
522
+ if line.end_with?(CHUNK_VALID_ENDING)
513
523
  # Puma doesn't process chunk extensions, but should parse if they're
514
524
  # present, which is the reason for the semicolon regex
515
525
  chunk_hex = line.strip[/\A[^;]+/]
@@ -521,19 +531,39 @@ module Puma
521
531
  @in_last_chunk = true
522
532
  @body.rewind
523
533
  rest = io.read
524
- last_crlf_size = "\r\n".bytesize
525
- if rest.bytesize < last_crlf_size
534
+ if rest.bytesize < CHUNK_VALID_ENDING_SIZE
526
535
  @buffer = nil
527
- @partial_part_left = last_crlf_size - rest.bytesize
536
+ @partial_part_left = CHUNK_VALID_ENDING_SIZE - rest.bytesize
528
537
  return false
529
538
  else
530
- @buffer = rest[last_crlf_size..-1]
539
+ # if the next character is a CRLF, set buffer to everything after that CRLF
540
+ start_of_rest = if rest.start_with?(CHUNK_VALID_ENDING)
541
+ CHUNK_VALID_ENDING_SIZE
542
+ else # we have started a trailer section, which we do not support. skip it!
543
+ rest.index(CHUNK_VALID_ENDING*2) + CHUNK_VALID_ENDING_SIZE*2
544
+ end
545
+
546
+ @buffer = rest[start_of_rest..-1]
531
547
  @buffer = nil if @buffer.empty?
532
548
  set_ready
533
549
  return true
534
550
  end
535
551
  end
536
552
 
553
+ # Track the excess as a function of the size of the
554
+ # header vs the size of the actual data. Excess can
555
+ # go negative (and is expected to) when the body is
556
+ # significant.
557
+ # The additional of chunk_hex.size and 2 compensates
558
+ # for a client sending 1 byte in a chunked body over
559
+ # a long period of time, making sure that that client
560
+ # isn't accidentally eventually punished.
561
+ @excess_cr += (line.size - len - chunk_hex.size - 2)
562
+
563
+ if @excess_cr >= MAX_CHUNK_EXCESS
564
+ raise HttpParserError, "Maximum chunk excess detected"
565
+ end
566
+
537
567
  len += 2
538
568
 
539
569
  part = io.read(len)
@@ -561,6 +591,10 @@ module Puma
561
591
  @partial_part_left = len - part.size
562
592
  end
563
593
  else
594
+ if @prev_chunk.size + chunk.size >= MAX_CHUNK_HEADER_SIZE
595
+ raise HttpParserError, "maximum size of chunk header exceeded"
596
+ end
597
+
564
598
  @prev_chunk = line
565
599
  return false
566
600
  end
File without changes
File without changes
data/lib/puma/cluster.rb CHANGED
File without changes
File without changes
File without changes
data/lib/puma/const.rb CHANGED
@@ -100,7 +100,7 @@ module Puma
100
100
  # too taxing on performance.
101
101
  module Const
102
102
 
103
- PUMA_VERSION = VERSION = "5.6.4".freeze
103
+ PUMA_VERSION = VERSION = "5.6.8".freeze
104
104
  CODE_NAME = "Birdie's Version".freeze
105
105
 
106
106
  PUMA_SERVER_STRING = ['puma', PUMA_VERSION, CODE_NAME].join(' ').freeze
@@ -17,26 +17,30 @@ module Puma
17
17
  CMD_PATH_SIG_MAP = {
18
18
  'gc' => nil,
19
19
  'gc-stats' => nil,
20
- 'halt' => 'SIGQUIT',
21
- 'phased-restart' => 'SIGUSR1',
22
- 'refork' => 'SIGURG',
20
+ 'halt' => 'SIGQUIT',
21
+ 'info' => 'SIGINFO',
22
+ 'phased-restart' => 'SIGUSR1',
23
+ 'refork' => 'SIGURG',
23
24
  'reload-worker-directory' => nil,
24
- 'restart' => 'SIGUSR2',
25
+ 'reopen-log' => 'SIGHUP',
26
+ 'restart' => 'SIGUSR2',
25
27
  'start' => nil,
26
28
  'stats' => nil,
27
29
  'status' => '',
28
- 'stop' => 'SIGTERM',
29
- 'thread-backtraces' => nil
30
+ 'stop' => 'SIGTERM',
31
+ 'thread-backtraces' => nil,
32
+ 'worker-count-down' => 'SIGTTOU',
33
+ 'worker-count-up' => 'SIGTTIN'
30
34
  }.freeze
31
35
 
32
36
  # @deprecated 6.0.0
33
37
  COMMANDS = CMD_PATH_SIG_MAP.keys.freeze
34
38
 
35
39
  # commands that cannot be used in a request
36
- NO_REQ_COMMANDS = %w{refork}.freeze
40
+ NO_REQ_COMMANDS = %w[info reopen-log worker-count-down worker-count-up].freeze
37
41
 
38
42
  # @version 5.0.0
39
- PRINTABLE_COMMANDS = %w{gc-stats stats thread-backtraces}.freeze
43
+ PRINTABLE_COMMANDS = %w[gc-stats stats thread-backtraces].freeze
40
44
 
41
45
  def initialize(argv, stdout=STDOUT, stderr=STDERR)
42
46
  @state = nil
@@ -185,8 +189,6 @@ module Puma
185
189
 
186
190
  if @command == 'status'
187
191
  message 'Puma is started'
188
- elsif NO_REQ_COMMANDS.include? @command
189
- raise "Invalid request command: #{@command}"
190
192
  else
191
193
  url = "/#{@command}"
192
194
 
@@ -242,7 +244,11 @@ module Puma
242
244
  @stdout.flush unless @stdout.sync
243
245
  return
244
246
  elsif sig.start_with? 'SIG'
245
- Process.kill sig, @pid
247
+ if Signal.list.key? sig.sub(/\ASIG/, '')
248
+ Process.kill sig, @pid
249
+ else
250
+ raise "Signal '#{sig}' not available'"
251
+ end
246
252
  elsif @command == 'status'
247
253
  begin
248
254
  Process.kill 0, @pid
@@ -268,7 +274,7 @@ module Puma
268
274
  return start if @command == 'start'
269
275
  prepare_configuration
270
276
 
271
- if Puma.windows? || @control_url
277
+ if Puma.windows? || @control_url && !NO_REQ_COMMANDS.include?(@command)
272
278
  send_request
273
279
  else
274
280
  send_signal
data/lib/puma/detect.rb CHANGED
File without changes
data/lib/puma/dsl.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'puma/const'
4
+ require 'puma/util'
4
5
 
5
6
  module Puma
6
7
  # The methods that are available for use inside the configuration file.
@@ -46,7 +47,7 @@ module Puma
46
47
  else ''
47
48
  end
48
49
 
49
- ca_additions = "&ca=#{opts[:ca]}" if ['peer', 'force_peer'].include?(verify)
50
+ ca_additions = "&ca=#{Puma::Util.escape(opts[:ca])}" if ['peer', 'force_peer'].include?(verify)
50
51
 
51
52
  backlog_str = opts[:backlog] ? "&backlog=#{Integer(opts[:backlog])}" : ''
52
53
 
@@ -65,7 +66,10 @@ module Puma
65
66
  v_flags = (ary = opts[:verification_flags]) ?
66
67
  "&verification_flags=#{Array(ary).join ','}" : nil
67
68
 
68
- "ssl://#{host}:#{port}?cert=#{opts[:cert]}&key=#{opts[:key]}" \
69
+ cert_flags = (cert = opts[:cert]) ? "cert=#{Puma::Util.escape(opts[:cert])}" : nil
70
+ key_flags = (cert = opts[:key]) ? "&key=#{Puma::Util.escape(opts[:key])}" : nil
71
+
72
+ "ssl://#{host}:#{port}?#{cert_flags}#{key_flags}" \
69
73
  "#{ssl_cipher_filter}&verify_mode=#{verify}#{tls_str}#{ca_additions}#{v_flags}#{backlog_str}"
70
74
  end
71
75
  end
File without changes
data/lib/puma/events.rb CHANGED
File without changes
File without changes
File without changes
File without changes
data/lib/puma/launcher.rb CHANGED
@@ -159,6 +159,17 @@ module Puma
159
159
  true
160
160
  end
161
161
 
162
+ # Begin a refork if supported
163
+ def refork
164
+ if clustered? && @runner.respond_to?(:fork_worker!) && @options[:fork_worker]
165
+ @runner.fork_worker!
166
+ true
167
+ else
168
+ log "* refork called but not available."
169
+ false
170
+ end
171
+ end
172
+
162
173
  # Run the server. This blocks until the server is stopped
163
174
  def run
164
175
  previous_env =
File without changes
data/lib/puma/minissl.rb CHANGED
@@ -214,6 +214,11 @@ module Puma
214
214
  @cert_pem = nil
215
215
  end
216
216
 
217
+ def check_file(file, desc)
218
+ raise ArgumentError, "#{desc} file '#{file}' does not exist" unless File.exist? file
219
+ raise ArgumentError, "#{desc} file '#{file}' is not readable" unless File.readable? file
220
+ end
221
+
217
222
  if IS_JRUBY
218
223
  # jruby-specific Context properties: java uses a keystore and password pair rather than a cert/key pair
219
224
  attr_reader :keystore
@@ -221,7 +226,7 @@ module Puma
221
226
  attr_accessor :ssl_cipher_list
222
227
 
223
228
  def keystore=(keystore)
224
- raise ArgumentError, "No such keystore file '#{keystore}'" unless File.exist? keystore
229
+ check_file keystore, 'Keystore'
225
230
  @keystore = keystore
226
231
  end
227
232
 
@@ -240,17 +245,17 @@ module Puma
240
245
  attr_accessor :verification_flags
241
246
 
242
247
  def key=(key)
243
- raise ArgumentError, "No such key file '#{key}'" unless File.exist? key
248
+ check_file key, 'Key'
244
249
  @key = key
245
250
  end
246
251
 
247
252
  def cert=(cert)
248
- raise ArgumentError, "No such cert file '#{cert}'" unless File.exist? cert
253
+ check_file cert, 'Cert'
249
254
  @cert = cert
250
255
  end
251
256
 
252
257
  def ca=(ca)
253
- raise ArgumentError, "No such ca file '#{ca}'" unless File.exist? ca
258
+ check_file ca, 'ca'
254
259
  @ca = ca
255
260
  end
256
261
 
data/lib/puma/null_io.rb CHANGED
@@ -52,5 +52,10 @@ module Puma
52
52
  def flush
53
53
  self
54
54
  end
55
+
56
+ # This is used as singleton class, so can't have state.
57
+ def closed?
58
+ false
59
+ end
55
60
  end
56
61
  end
File without changes
data/lib/puma/plugin.rb CHANGED
File without changes
File without changes
File without changes
File without changes
File without changes
data/lib/puma/reactor.rb CHANGED
File without changes
data/lib/puma/request.rb CHANGED
@@ -178,7 +178,11 @@ module Puma
178
178
  res_body.close if res_body.respond_to? :close
179
179
  end
180
180
 
181
- after_reply.each { |o| o.call }
181
+ begin
182
+ after_reply.each { |o| o.call }
183
+ rescue StandardError => e
184
+ @log_writer.debug_error e
185
+ end
182
186
  end
183
187
 
184
188
  res_info[:keep_alive]
data/lib/puma/runner.rb CHANGED
File without changes
data/lib/puma/server.rb CHANGED
@@ -39,6 +39,7 @@ module Puma
39
39
  attr_reader :events
40
40
  attr_reader :min_threads, :max_threads # for #stats
41
41
  attr_reader :requests_count # @version 5.0.0
42
+ attr_reader :log_writer # to help with backports
42
43
 
43
44
  # @todo the following may be deprecated in the future
44
45
  attr_reader :auto_trim_time, :early_hints, :first_data_timeout,
@@ -73,6 +74,7 @@ module Puma
73
74
  def initialize(app, events=Events.stdio, options={})
74
75
  @app = app
75
76
  @events = events
77
+ @log_writer = events
76
78
 
77
79
  @check, @notify = nil
78
80
  @status = :stop
data/lib/puma/single.rb CHANGED
File without changes
@@ -50,6 +50,7 @@ module Puma
50
50
  v = v.strip
51
51
  @options[k] =
52
52
  case v
53
+ when '' then nil
53
54
  when /\A\d+\z/ then v.to_i
54
55
  when /\A\d+\.\d+\z/ then v.to_f
55
56
  else v.gsub(/\A"|"\z/, '')
data/lib/puma/systemd.rb CHANGED
File without changes
File without changes
data/lib/puma/util.rb CHANGED
@@ -17,18 +17,27 @@ module Puma
17
17
  Thread.current.purge_interrupt_queue if Thread.current.respond_to? :purge_interrupt_queue
18
18
  end
19
19
 
20
- # Unescapes a URI escaped string with +encoding+. +encoding+ will be the
21
- # target encoding of the string returned, and it defaults to UTF-8
20
+ # Escapes and unescapes a URI escaped string with
21
+ # +encoding+. +encoding+ will be the target encoding of the string
22
+ # returned, and it defaults to UTF-8
22
23
  if defined?(::Encoding)
24
+ def escape(s, encoding = Encoding::UTF_8)
25
+ URI.encode_www_form_component(s, encoding)
26
+ end
27
+
23
28
  def unescape(s, encoding = Encoding::UTF_8)
24
29
  URI.decode_www_form_component(s, encoding)
25
30
  end
26
31
  else
32
+ def escape(s, encoding = nil)
33
+ URI.encode_www_form_component(s, encoding)
34
+ end
35
+
27
36
  def unescape(s, encoding = nil)
28
37
  URI.decode_www_form_component(s, encoding)
29
38
  end
30
39
  end
31
- module_function :unescape
40
+ module_function :unescape, :escape
32
41
 
33
42
  # @version 5.0.0
34
43
  def nakayoshi_gc(events)
data/lib/puma.rb CHANGED
@@ -10,9 +10,11 @@ require 'stringio'
10
10
 
11
11
  require 'thread'
12
12
 
13
+ # extension files should not be loaded with `require_relative`
13
14
  require 'puma/puma_http11'
14
- require 'puma/detect'
15
- require 'puma/json_serialization'
15
+ require_relative 'puma/detect'
16
+ require_relative 'puma/json_serialization'
17
+ require_relative 'rack/version_restriction'
16
18
 
17
19
  module Puma
18
20
  autoload :Const, 'puma/const'
@@ -23,7 +25,7 @@ module Puma
23
25
  # not in minissl.rb
24
26
  HAS_SSL = const_defined?(:MiniSSL, false) && MiniSSL.const_defined?(:Engine, false)
25
27
 
26
- HAS_UNIX_SOCKET = Object.const_defined? :UNIXSocket
28
+ HAS_UNIX_SOCKET = Object.const_defined?(:UNIXSocket) && !IS_WINDOWS
27
29
 
28
30
  if HAS_SSL
29
31
  require 'puma/minissl'
File without changes
@@ -0,0 +1,15 @@
1
+ begin
2
+ begin
3
+ # rack/version exists in Rack 2.2.0 and later, compatible with Ruby 2.3 and later
4
+ # we prefer to not load Rack
5
+ require 'rack/version'
6
+ rescue LoadError
7
+ require 'rack'
8
+ end
9
+
10
+ # Rack.release is needed for Rack v1, Rack::RELEASE was added in v2
11
+ if Gem::Version.new(Rack.release) >= Gem::Version.new("3.0.0")
12
+ raise StandardError.new "Puma 5 is not compatible with Rack 3, please upgrade to Puma 6 or higher."
13
+ end
14
+ rescue LoadError
15
+ end
data/tools/Dockerfile CHANGED
File without changes
data/tools/trickletest.rb CHANGED
File without changes
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: puma
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.6.4
4
+ version: 5.6.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Evan Phoenix
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 1980-01-01 00:00:00.000000000 Z
11
+ date: 2024-01-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nio4r
@@ -115,6 +115,7 @@ files:
115
115
  - lib/puma/thread_pool.rb
116
116
  - lib/puma/util.rb
117
117
  - lib/rack/handler/puma.rb
118
+ - lib/rack/version_restriction.rb
118
119
  - tools/Dockerfile
119
120
  - tools/trickletest.rb
120
121
  homepage: https://puma.io
@@ -140,7 +141,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
140
141
  - !ruby/object:Gem::Version
141
142
  version: '0'
142
143
  requirements: []
143
- rubygems_version: 3.2.26
144
+ rubygems_version: 3.5.3
144
145
  signing_key:
145
146
  specification_version: 4
146
147
  summary: Puma is a simple, fast, threaded, and highly parallel HTTP 1.1 server for