puma 3.12.6 → 6.2.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 (100) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +1775 -451
  3. data/LICENSE +23 -20
  4. data/README.md +193 -65
  5. data/bin/puma-wild +3 -9
  6. data/docs/architecture.md +59 -21
  7. data/docs/compile_options.md +55 -0
  8. data/docs/deployment.md +69 -58
  9. data/docs/fork_worker.md +31 -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 +2 -2
  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 +94 -120
  25. data/docs/testing_benchmarks_local_files.md +150 -0
  26. data/docs/testing_test_rackup_ci_files.md +36 -0
  27. data/ext/puma_http11/PumaHttp11Service.java +2 -2
  28. data/ext/puma_http11/ext_help.h +1 -1
  29. data/ext/puma_http11/extconf.rb +61 -3
  30. data/ext/puma_http11/http11_parser.c +103 -117
  31. data/ext/puma_http11/http11_parser.h +2 -2
  32. data/ext/puma_http11/http11_parser.java.rl +22 -38
  33. data/ext/puma_http11/http11_parser.rl +3 -3
  34. data/ext/puma_http11/http11_parser_common.rl +6 -6
  35. data/ext/puma_http11/mini_ssl.c +361 -99
  36. data/ext/puma_http11/no_ssl/PumaHttp11Service.java +15 -0
  37. data/ext/puma_http11/org/jruby/puma/Http11.java +108 -116
  38. data/ext/puma_http11/org/jruby/puma/Http11Parser.java +84 -99
  39. data/ext/puma_http11/org/jruby/puma/MiniSSL.java +248 -92
  40. data/ext/puma_http11/puma_http11.c +49 -57
  41. data/lib/puma/app/status.rb +71 -49
  42. data/lib/puma/binder.rb +242 -150
  43. data/lib/puma/cli.rb +38 -34
  44. data/lib/puma/client.rb +387 -244
  45. data/lib/puma/cluster/worker.rb +180 -0
  46. data/lib/puma/cluster/worker_handle.rb +97 -0
  47. data/lib/puma/cluster.rb +261 -243
  48. data/lib/puma/commonlogger.rb +21 -14
  49. data/lib/puma/configuration.rb +116 -88
  50. data/lib/puma/const.rb +101 -100
  51. data/lib/puma/control_cli.rb +115 -70
  52. data/lib/puma/detect.rb +33 -2
  53. data/lib/puma/dsl.rb +731 -134
  54. data/lib/puma/error_logger.rb +113 -0
  55. data/lib/puma/events.rb +16 -112
  56. data/lib/puma/io_buffer.rb +42 -5
  57. data/lib/puma/jruby_restart.rb +2 -59
  58. data/lib/puma/json_serialization.rb +96 -0
  59. data/lib/puma/launcher/bundle_pruner.rb +104 -0
  60. data/lib/puma/launcher.rb +184 -133
  61. data/lib/puma/log_writer.rb +147 -0
  62. data/lib/puma/minissl/context_builder.rb +92 -0
  63. data/lib/puma/minissl.rb +246 -70
  64. data/lib/puma/null_io.rb +18 -1
  65. data/lib/puma/plugin/systemd.rb +90 -0
  66. data/lib/puma/plugin/tmp_restart.rb +3 -1
  67. data/lib/puma/plugin.rb +7 -13
  68. data/lib/puma/rack/builder.rb +7 -9
  69. data/lib/puma/rack/urlmap.rb +2 -0
  70. data/lib/puma/rack_default.rb +21 -4
  71. data/lib/puma/reactor.rb +85 -316
  72. data/lib/puma/request.rb +665 -0
  73. data/lib/puma/runner.rb +94 -69
  74. data/lib/puma/sd_notify.rb +149 -0
  75. data/lib/puma/server.rb +314 -771
  76. data/lib/puma/single.rb +20 -74
  77. data/lib/puma/state_file.rb +45 -8
  78. data/lib/puma/thread_pool.rb +142 -92
  79. data/lib/puma/util.rb +22 -10
  80. data/lib/puma.rb +60 -5
  81. data/lib/rack/handler/puma.rb +113 -91
  82. data/tools/Dockerfile +16 -0
  83. data/tools/trickletest.rb +0 -1
  84. metadata +54 -32
  85. data/ext/puma_http11/io_buffer.c +0 -155
  86. data/lib/puma/accept_nonblock.rb +0 -23
  87. data/lib/puma/compat.rb +0 -14
  88. data/lib/puma/convenient.rb +0 -25
  89. data/lib/puma/daemon_ext.rb +0 -33
  90. data/lib/puma/delegation.rb +0 -13
  91. data/lib/puma/java_io_buffer.rb +0 -47
  92. data/lib/puma/rack/backports/uri/common_193.rb +0 -33
  93. data/lib/puma/tcp_logger.rb +0 -41
  94. data/tools/jungle/README.md +0 -19
  95. data/tools/jungle/init.d/README.md +0 -61
  96. data/tools/jungle/init.d/puma +0 -421
  97. data/tools/jungle/init.d/run-puma +0 -18
  98. data/tools/jungle/upstart/README.md +0 -61
  99. data/tools/jungle/upstart/puma-manager.conf +0 -31
  100. 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,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,45 +185,173 @@ 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;
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;
230
+
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
235
+
236
+ key = rb_funcall(mini_ssl_ctx, rb_intern_const("key"), 0);
237
+
238
+ cert = rb_funcall(mini_ssl_ctx, rb_intern_const("cert"), 0);
145
239
 
146
- ms_conn* conn = engine_alloc(self, &obj);
240
+ ca = rb_funcall(mini_ssl_ctx, rb_intern_const("ca"), 0);
147
241
 
148
- ID sym_key = rb_intern("key");
149
- VALUE key = rb_funcall(mini_ssl_ctx, sym_key, 0);
242
+ cert_pem = rb_funcall(mini_ssl_ctx, rb_intern_const("cert_pem"), 0);
150
243
 
151
- StringValue(key);
244
+ key_pem = rb_funcall(mini_ssl_ctx, rb_intern_const("key_pem"), 0);
152
245
 
153
- ID sym_cert = rb_intern("cert");
154
- VALUE cert = rb_funcall(mini_ssl_ctx, sym_cert, 0);
246
+ verify_mode = rb_funcall(mini_ssl_ctx, rb_intern_const("verify_mode"), 0);
155
247
 
156
- StringValue(cert);
248
+ ssl_cipher_filter = rb_funcall(mini_ssl_ctx, rb_intern_const("ssl_cipher_filter"), 0);
157
249
 
158
- ID sym_ca = rb_intern("ca");
159
- VALUE ca = rb_funcall(mini_ssl_ctx, sym_ca, 0);
250
+ no_tlsv1 = rb_funcall(mini_ssl_ctx, rb_intern_const("no_tlsv1"), 0);
251
+
252
+ no_tlsv1_1 = rb_funcall(mini_ssl_ctx, rb_intern_const("no_tlsv1_1"), 0);
253
+
254
+ TypedData_Get_Struct(self, SSL_CTX, &sslctx_type, ctx);
255
+
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
+ }
160
284
 
161
- ID sym_verify_mode = rb_intern("verify_mode");
162
- VALUE verify_mode = rb_funcall(mini_ssl_ctx, sym_verify_mode, 0);
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);
163
289
 
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);
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
+ }
166
297
 
167
- ctx = SSL_CTX_new(SSLv23_server_method());
168
- conn->ctx = ctx;
298
+ verification_flags = rb_funcall(mini_ssl_ctx, rb_intern_const("verification_flags"), 0);
169
299
 
170
- SSL_CTX_use_certificate_chain_file(ctx, RSTRING_PTR(cert));
171
- SSL_CTX_use_PrivateKey_file(ctx, RSTRING_PTR(key), SSL_FILETYPE_PEM);
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
+ }
172
305
 
173
306
  if (!NIL_P(ca)) {
174
307
  StringValue(ca);
175
- 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
+ }
311
+ }
312
+
313
+ ssl_options = SSL_OP_CIPHER_SERVER_PREFERENCE | SSL_OP_SINGLE_ECDH_USE | SSL_OP_NO_COMPRESSION;
314
+
315
+ #ifdef HAVE_SSL_CTX_SET_MIN_PROTO_VERSION
316
+ if (RTEST(no_tlsv1_1)) {
317
+ min = TLS1_2_VERSION;
318
+ }
319
+ else if (RTEST(no_tlsv1)) {
320
+ min = TLS1_1_VERSION;
321
+ }
322
+ else {
323
+ min = TLS1_VERSION;
324
+ }
325
+
326
+ SSL_CTX_set_min_proto_version(ctx, min);
327
+
328
+ #else
329
+ /* As of 1.0.2f, SSL_OP_SINGLE_DH_USE key use is always on */
330
+ ssl_options |= SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_SINGLE_DH_USE;
331
+
332
+ if (RTEST(no_tlsv1)) {
333
+ ssl_options |= SSL_OP_NO_TLSv1;
334
+ }
335
+ if(RTEST(no_tlsv1_1)) {
336
+ ssl_options |= SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1;
337
+ }
338
+ #endif
339
+
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);
176
351
  }
352
+ #endif
177
353
 
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);
179
- SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
354
+ SSL_CTX_set_options(ctx, ssl_options);
180
355
 
181
356
  if (!NIL_P(ssl_cipher_filter)) {
182
357
  StringValue(ssl_cipher_filter);
@@ -186,29 +361,65 @@ VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) {
186
361
  SSL_CTX_set_cipher_list(ctx, "HIGH:!aNULL@STRENGTH");
187
362
  }
188
363
 
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);
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);
194
367
  if (ecdh) {
195
368
  SSL_CTX_set_tmp_ecdh(ctx, ecdh);
196
369
  EC_KEY_free(ecdh);
197
370
  }
371
+ #elif OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
372
+ SSL_CTX_set_ecdh_auto(ctx, 1);
198
373
  #endif
199
374
 
200
- ssl = SSL_new(ctx);
201
- conn->ssl = ssl;
202
- SSL_set_app_data(ssl, NULL);
203
-
204
375
  if (NIL_P(verify_mode)) {
205
- /* SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL); */
376
+ /* SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); */
206
377
  } else {
207
- SSL_set_verify(ssl, NUM2INT(verify_mode), engine_verify_callback);
378
+ SSL_CTX_set_verify(ctx, NUM2INT(verify_mode), engine_verify_callback);
208
379
  }
209
380
 
210
- SSL_set_bio(ssl, conn->read, conn->write);
381
+ // Random.bytes available in Ruby 2.5 and later, Random::DEFAULT deprecated in 3.0
382
+ session_id_bytes = rb_funcall(
383
+ #ifdef HAVE_RANDOM_BYTES
384
+ rb_cRandom,
385
+ #else
386
+ rb_const_get(rb_cRandom, rb_intern_const("DEFAULT")),
387
+ #endif
388
+ rb_intern_const("bytes"),
389
+ 1, ULL2NUM(SSL_MAX_SSL_SESSION_ID_LENGTH));
390
+
391
+ SSL_CTX_set_session_id_context(ctx,
392
+ (unsigned char *) RSTRING_PTR(session_id_bytes),
393
+ SSL_MAX_SSL_SESSION_ID_LENGTH);
394
+
395
+ // printf("\ninitialize end security_level %d\n", SSL_CTX_get_security_level(ctx));
396
+
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);
403
+ #endif
211
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
+
419
+ ssl = SSL_new(ctx);
420
+ conn->ssl = ssl;
421
+ SSL_set_app_data(ssl, NULL);
422
+ SSL_set_bio(ssl, conn->read, conn->write);
212
423
  SSL_set_accept_state(ssl);
213
424
  return obj;
214
425
  }
@@ -216,8 +427,11 @@ VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) {
216
427
  VALUE engine_init_client(VALUE klass) {
217
428
  VALUE obj;
218
429
  ms_conn* conn = engine_alloc(klass, &obj);
219
-
430
+ #ifdef HAVE_DTLS_METHOD
431
+ conn->ctx = SSL_CTX_new(DTLS_method());
432
+ #else
220
433
  conn->ctx = SSL_CTX_new(DTLSv1_method());
434
+ #endif
221
435
  conn->ssl = SSL_new(conn->ctx);
222
436
  SSL_set_app_data(conn->ssl, NULL);
223
437
  SSL_set_verify(conn->ssl, SSL_VERIFY_NONE, NULL);
@@ -232,7 +446,7 @@ VALUE engine_inject(VALUE self, VALUE str) {
232
446
  ms_conn* conn;
233
447
  long used;
234
448
 
235
- Data_Get_Struct(self, ms_conn, conn);
449
+ TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
236
450
 
237
451
  StringValue(str);
238
452
 
@@ -245,13 +459,14 @@ VALUE engine_inject(VALUE self, VALUE str) {
245
459
  return INT2FIX(used);
246
460
  }
247
461
 
248
- static VALUE eError;
462
+ NORETURN(void raise_error(SSL* ssl, int result));
249
463
 
250
464
  void raise_error(SSL* ssl, int result) {
251
465
  char buf[512];
252
466
  char msg[512];
253
467
  const char* err_str;
254
468
  int err = errno;
469
+ int mask = 4095;
255
470
  int ssl_err = SSL_get_error(ssl, result);
256
471
  int verify_err = (int) SSL_get_verify_result(ssl);
257
472
 
@@ -268,8 +483,7 @@ void raise_error(SSL* ssl, int result) {
268
483
  } else {
269
484
  err = (int) ERR_get_error();
270
485
  ERR_error_string_n(err, buf, sizeof(buf));
271
- snprintf(msg, sizeof(msg), "OpenSSL error: %s - %d", buf, err);
272
-
486
+ snprintf(msg, sizeof(msg), "OpenSSL error: %s - %d", buf, err & mask);
273
487
  }
274
488
  } else {
275
489
  snprintf(msg, sizeof(msg), "Unknown OpenSSL error: %d", ssl_err);
@@ -284,7 +498,7 @@ VALUE engine_read(VALUE self) {
284
498
  char buf[512];
285
499
  int bytes, error;
286
500
 
287
- Data_Get_Struct(self, ms_conn, conn);
501
+ TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
288
502
 
289
503
  ERR_clear_error();
290
504
 
@@ -311,7 +525,7 @@ VALUE engine_write(VALUE self, VALUE str) {
311
525
  ms_conn* conn;
312
526
  int bytes;
313
527
 
314
- Data_Get_Struct(self, ms_conn, conn);
528
+ TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
315
529
 
316
530
  StringValue(str);
317
531
 
@@ -333,9 +547,11 @@ VALUE engine_extract(VALUE self) {
333
547
  ms_conn* conn;
334
548
  int bytes;
335
549
  size_t pending;
336
- 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];
337
553
 
338
- Data_Get_Struct(self, ms_conn, conn);
554
+ TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
339
555
 
340
556
  pending = BIO_pending(conn->write);
341
557
  if(pending > 0) {
@@ -354,7 +570,7 @@ VALUE engine_shutdown(VALUE self) {
354
570
  ms_conn* conn;
355
571
  int ok;
356
572
 
357
- Data_Get_Struct(self, ms_conn, conn);
573
+ TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
358
574
 
359
575
  ERR_clear_error();
360
576
 
@@ -369,7 +585,7 @@ VALUE engine_shutdown(VALUE self) {
369
585
  VALUE engine_init(VALUE self) {
370
586
  ms_conn* conn;
371
587
 
372
- Data_Get_Struct(self, ms_conn, conn);
588
+ TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
373
589
 
374
590
  return SSL_in_init(conn->ssl) ? Qtrue : Qfalse;
375
591
  }
@@ -382,9 +598,13 @@ VALUE engine_peercert(VALUE self) {
382
598
  ms_cert_buf* cert_buf = NULL;
383
599
  VALUE rb_cert_buf;
384
600
 
385
- Data_Get_Struct(self, ms_conn, conn);
601
+ TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
386
602
 
603
+ #ifdef HAVE_SSL_GET1_PEER_CERTIFICATE
604
+ cert = SSL_get1_peer_certificate(conn->ssl);
605
+ #else
387
606
  cert = SSL_get_peer_certificate(conn->ssl);
607
+ #endif
388
608
  if(!cert) {
389
609
  /*
390
610
  * See if there was a failed certificate associated with this client.
@@ -413,12 +633,22 @@ VALUE engine_peercert(VALUE self) {
413
633
  return rb_cert_buf;
414
634
  }
415
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
+
416
646
  VALUE noop(VALUE self) {
417
647
  return Qnil;
418
648
  }
419
649
 
420
650
  void Init_mini_ssl(VALUE puma) {
421
- VALUE mod, eng;
651
+ VALUE mod, eng, sslctx;
422
652
 
423
653
  /* Fake operation for documentation (RDoc, YARD) */
424
654
  #if 0 == 1
@@ -431,18 +661,47 @@ void Init_mini_ssl(VALUE puma) {
431
661
  ERR_load_crypto_strings();
432
662
 
433
663
  mod = rb_define_module_under(puma, "MiniSSL");
664
+
434
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
+
435
673
 
436
674
  // OpenSSL Build / Runtime/Load versions
437
675
 
438
676
  /* Version of OpenSSL that Puma was compiled with */
439
- rb_define_const(mod, "OPENSSL_VERSION", rb_str_new2(OPENSSL_VERSION_TEXT));
677
+ rb_define_const(mod, "OPENSSL_VERSION", rb_str_new2(OPENSSL_VERSION_TEXT));
440
678
 
441
679
  #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)));
680
+ /* Version of OpenSSL that Puma loaded with */
681
+ rb_define_const(mod, "OPENSSL_LIBRARY_VERSION", rb_str_new2(OpenSSL_version(OPENSSL_VERSION)));
682
+ #else
683
+ rb_define_const(mod, "OPENSSL_LIBRARY_VERSION", rb_str_new2(SSLeay_version(SSLEAY_VERSION)));
684
+ #endif
685
+
686
+ #if defined(OPENSSL_NO_SSL3) || defined(OPENSSL_NO_SSL3_METHOD)
687
+ /* True if SSL3 is not available */
688
+ rb_define_const(mod, "OPENSSL_NO_SSL3", Qtrue);
444
689
  #else
445
- rb_define_const(mod, "OPENSSL_LIBRARY_VERSION", rb_str_new2(SSLeay_version(SSLEAY_VERSION)));
690
+ rb_define_const(mod, "OPENSSL_NO_SSL3", Qfalse);
691
+ #endif
692
+
693
+ #if defined(OPENSSL_NO_TLS1) || defined(OPENSSL_NO_TLS1_METHOD)
694
+ /* True if TLS1 is not available */
695
+ rb_define_const(mod, "OPENSSL_NO_TLS1", Qtrue);
696
+ #else
697
+ rb_define_const(mod, "OPENSSL_NO_TLS1", Qfalse);
698
+ #endif
699
+
700
+ #if defined(OPENSSL_NO_TLS1_1) || defined(OPENSSL_NO_TLS1_1_METHOD)
701
+ /* True if TLS1_1 is not available */
702
+ rb_define_const(mod, "OPENSSL_NO_TLS1_1", Qtrue);
703
+ #else
704
+ rb_define_const(mod, "OPENSSL_NO_TLS1_1", Qfalse);
446
705
  #endif
447
706
 
448
707
  rb_define_singleton_method(mod, "check", noop, 0);
@@ -463,13 +722,16 @@ void Init_mini_ssl(VALUE puma) {
463
722
  rb_define_method(eng, "init?", engine_init, 0);
464
723
 
465
724
  rb_define_method(eng, "peercert", engine_peercert, 0);
725
+
726
+ rb_define_method(eng, "ssl_vers_st", engine_ssl_vers_st, 0);
466
727
  }
467
728
 
468
729
  #else
469
730
 
731
+ NORETURN(VALUE raise_error(VALUE self));
732
+
470
733
  VALUE raise_error(VALUE self) {
471
734
  rb_raise(rb_eStandardError, "SSL not available in this build");
472
- return Qnil;
473
735
  }
474
736
 
475
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
+ }