puma 4.3.5 → 6.0.1

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 (95) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +1639 -519
  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/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 +15 -15
  20. data/docs/rails_dev_mode.md +28 -0
  21. data/docs/restart.md +46 -23
  22. data/docs/signals.md +13 -11
  23. data/docs/stats.md +142 -0
  24. data/docs/systemd.md +85 -128
  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 -4
  28. data/ext/puma_http11/ext_help.h +1 -1
  29. data/ext/puma_http11/extconf.rb +56 -11
  30. data/ext/puma_http11/http11_parser.c +69 -58
  31. data/ext/puma_http11/http11_parser.h +2 -2
  32. data/ext/puma_http11/http11_parser.java.rl +3 -3
  33. data/ext/puma_http11/http11_parser.rl +3 -3
  34. data/ext/puma_http11/http11_parser_common.rl +3 -3
  35. data/ext/puma_http11/mini_ssl.c +322 -130
  36. data/ext/puma_http11/no_ssl/PumaHttp11Service.java +15 -0
  37. data/ext/puma_http11/org/jruby/puma/Http11.java +6 -6
  38. data/ext/puma_http11/org/jruby/puma/Http11Parser.java +52 -52
  39. data/ext/puma_http11/org/jruby/puma/MiniSSL.java +241 -96
  40. data/ext/puma_http11/puma_http11.c +47 -57
  41. data/lib/puma/app/status.rb +53 -37
  42. data/lib/puma/binder.rb +232 -119
  43. data/lib/puma/cli.rb +33 -33
  44. data/lib/puma/client.rb +197 -101
  45. data/lib/puma/cluster/worker.rb +175 -0
  46. data/lib/puma/cluster/worker_handle.rb +97 -0
  47. data/lib/puma/cluster.rb +224 -229
  48. data/lib/puma/commonlogger.rb +2 -2
  49. data/lib/puma/configuration.rb +112 -87
  50. data/lib/puma/const.rb +30 -25
  51. data/lib/puma/control_cli.rb +99 -79
  52. data/lib/puma/detect.rb +31 -2
  53. data/lib/puma/dsl.rb +426 -110
  54. data/lib/puma/error_logger.rb +112 -0
  55. data/lib/puma/events.rb +16 -115
  56. data/lib/puma/io_buffer.rb +44 -2
  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 +170 -148
  61. data/lib/puma/log_writer.rb +137 -0
  62. data/lib/puma/minissl/context_builder.rb +35 -19
  63. data/lib/puma/minissl.rb +213 -55
  64. data/lib/puma/null_io.rb +18 -1
  65. data/lib/puma/plugin/tmp_restart.rb +1 -1
  66. data/lib/puma/plugin.rb +3 -12
  67. data/lib/puma/rack/builder.rb +5 -9
  68. data/lib/puma/rack/urlmap.rb +0 -0
  69. data/lib/puma/rack_default.rb +1 -1
  70. data/lib/puma/reactor.rb +85 -369
  71. data/lib/puma/request.rb +644 -0
  72. data/lib/puma/runner.rb +83 -77
  73. data/lib/puma/server.rb +303 -773
  74. data/lib/puma/single.rb +18 -74
  75. data/lib/puma/state_file.rb +45 -8
  76. data/lib/puma/systemd.rb +47 -0
  77. data/lib/puma/thread_pool.rb +136 -68
  78. data/lib/puma/util.rb +21 -4
  79. data/lib/puma.rb +54 -5
  80. data/lib/rack/handler/puma.rb +11 -12
  81. data/tools/{docker/Dockerfile → Dockerfile} +1 -1
  82. data/tools/trickletest.rb +0 -0
  83. metadata +36 -28
  84. data/docs/tcp_mode.md +0 -96
  85. data/ext/puma_http11/io_buffer.c +0 -155
  86. data/ext/puma_http11/org/jruby/puma/IOBuffer.java +0 -72
  87. data/lib/puma/accept_nonblock.rb +0 -29
  88. data/lib/puma/tcp_logger.rb +0 -41
  89. data/tools/jungle/README.md +0 -19
  90. data/tools/jungle/init.d/README.md +0 -61
  91. data/tools/jungle/init.d/puma +0 -421
  92. data/tools/jungle/init.d/run-puma +0 -18
  93. data/tools/jungle/upstart/README.md +0 -61
  94. data/tools/jungle/upstart/puma-manager.conf +0 -31
  95. 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;
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
+ };
61
57
 
62
- return conn;
63
- }
64
-
65
- DH *get_dh1024() {
66
- /* `openssl dhparam 1024 -C`
58
+ #ifndef HAVE_SSL_CTX_SET_DH_AUTO
59
+ DH *get_dh2048(void) {
60
+ /* `openssl dhparam -C 2048`
67
61
  * -----BEGIN DH PARAMETERS-----
68
- * MIGHAoGBALPwcEv0OstmQCZdfHw0N5r+07lmXMxkpQacy1blwj0LUqC+Divp6pBk
69
- * usTJ9W2/dOYr1X7zi6yXNLp4oLzc/31PUL3D9q8CpGS7vPz5gijKSw9BwCTT5z9+
70
- * KF9v46qw8XqT5HHV87sWFlGQcVFq+pEkA2kPikkKZ/X/CCcpCAV7AgEC
62
+ * MIIBCAKCAQEAjmh1uQHdTfxOyxEbKAV30fUfzqMDF/ChPzjfyzl2jcrqQMhrk76o
63
+ * 2NPNXqxHwsddMZ1RzvU8/jl+uhRuPWjXCFZbhET4N1vrviZM3VJhV8PPHuiVOACO
64
+ * y32jFd+Szx4bo2cXSK83hJ6jRd+0asP1awWjz9/06dFkrILCXMIfQLo0D8rqmppn
65
+ * EfDDAwuudCpM9kcDmBRAm9JsKbQ6gzZWjkc5+QWSaQofojIHbjvj3xzguaCJn+oQ
66
+ * vHWM+hsAnaOgEwCyeZ3xqs+/5lwSbkE/tqJW98cEZGygBUVo9jxZRZx6KOfjpdrb
67
+ * yenO9LJr/qtyrZB31WJbqxI0m0AKTAO8UwIBAg==
71
68
  * -----END DH PARAMETERS-----
72
69
  */
73
- static unsigned char dh1024_p[] = {
74
- 0xB3,0xF0,0x70,0x4B,0xF4,0x3A,0xCB,0x66,0x40,0x26,0x5D,0x7C,
75
- 0x7C,0x34,0x37,0x9A,0xFE,0xD3,0xB9,0x66,0x5C,0xCC,0x64,0xA5,
76
- 0x06,0x9C,0xCB,0x56,0xE5,0xC2,0x3D,0x0B,0x52,0xA0,0xBE,0x0E,
77
- 0x2B,0xE9,0xEA,0x90,0x64,0xBA,0xC4,0xC9,0xF5,0x6D,0xBF,0x74,
78
- 0xE6,0x2B,0xD5,0x7E,0xF3,0x8B,0xAC,0x97,0x34,0xBA,0x78,0xA0,
79
- 0xBC,0xDC,0xFF,0x7D,0x4F,0x50,0xBD,0xC3,0xF6,0xAF,0x02,0xA4,
80
- 0x64,0xBB,0xBC,0xFC,0xF9,0x82,0x28,0xCA,0x4B,0x0F,0x41,0xC0,
81
- 0x24,0xD3,0xE7,0x3F,0x7E,0x28,0x5F,0x6F,0xE3,0xAA,0xB0,0xF1,
82
- 0x7A,0x93,0xE4,0x71,0xD5,0xF3,0xBB,0x16,0x16,0x51,0x90,0x71,
83
- 0x51,0x6A,0xFA,0x91,0x24,0x03,0x69,0x0F,0x8A,0x49,0x0A,0x67,
84
- 0xF5,0xFF,0x08,0x27,0x29,0x08,0x05,0x7B
70
+ static unsigned char dh2048_p[] = {
71
+ 0x8E, 0x68, 0x75, 0xB9, 0x01, 0xDD, 0x4D, 0xFC, 0x4E, 0xCB,
72
+ 0x11, 0x1B, 0x28, 0x05, 0x77, 0xD1, 0xF5, 0x1F, 0xCE, 0xA3,
73
+ 0x03, 0x17, 0xF0, 0xA1, 0x3F, 0x38, 0xDF, 0xCB, 0x39, 0x76,
74
+ 0x8D, 0xCA, 0xEA, 0x40, 0xC8, 0x6B, 0x93, 0xBE, 0xA8, 0xD8,
75
+ 0xD3, 0xCD, 0x5E, 0xAC, 0x47, 0xC2, 0xC7, 0x5D, 0x31, 0x9D,
76
+ 0x51, 0xCE, 0xF5, 0x3C, 0xFE, 0x39, 0x7E, 0xBA, 0x14, 0x6E,
77
+ 0x3D, 0x68, 0xD7, 0x08, 0x56, 0x5B, 0x84, 0x44, 0xF8, 0x37,
78
+ 0x5B, 0xEB, 0xBE, 0x26, 0x4C, 0xDD, 0x52, 0x61, 0x57, 0xC3,
79
+ 0xCF, 0x1E, 0xE8, 0x95, 0x38, 0x00, 0x8E, 0xCB, 0x7D, 0xA3,
80
+ 0x15, 0xDF, 0x92, 0xCF, 0x1E, 0x1B, 0xA3, 0x67, 0x17, 0x48,
81
+ 0xAF, 0x37, 0x84, 0x9E, 0xA3, 0x45, 0xDF, 0xB4, 0x6A, 0xC3,
82
+ 0xF5, 0x6B, 0x05, 0xA3, 0xCF, 0xDF, 0xF4, 0xE9, 0xD1, 0x64,
83
+ 0xAC, 0x82, 0xC2, 0x5C, 0xC2, 0x1F, 0x40, 0xBA, 0x34, 0x0F,
84
+ 0xCA, 0xEA, 0x9A, 0x9A, 0x67, 0x11, 0xF0, 0xC3, 0x03, 0x0B,
85
+ 0xAE, 0x74, 0x2A, 0x4C, 0xF6, 0x47, 0x03, 0x98, 0x14, 0x40,
86
+ 0x9B, 0xD2, 0x6C, 0x29, 0xB4, 0x3A, 0x83, 0x36, 0x56, 0x8E,
87
+ 0x47, 0x39, 0xF9, 0x05, 0x92, 0x69, 0x0A, 0x1F, 0xA2, 0x32,
88
+ 0x07, 0x6E, 0x3B, 0xE3, 0xDF, 0x1C, 0xE0, 0xB9, 0xA0, 0x89,
89
+ 0x9F, 0xEA, 0x10, 0xBC, 0x75, 0x8C, 0xFA, 0x1B, 0x00, 0x9D,
90
+ 0xA3, 0xA0, 0x13, 0x00, 0xB2, 0x79, 0x9D, 0xF1, 0xAA, 0xCF,
91
+ 0xBF, 0xE6, 0x5C, 0x12, 0x6E, 0x41, 0x3F, 0xB6, 0xA2, 0x56,
92
+ 0xF7, 0xC7, 0x04, 0x64, 0x6C, 0xA0, 0x05, 0x45, 0x68, 0xF6,
93
+ 0x3C, 0x59, 0x45, 0x9C, 0x7A, 0x28, 0xE7, 0xE3, 0xA5, 0xDA,
94
+ 0xDB, 0xC9, 0xE9, 0xCE, 0xF4, 0xB2, 0x6B, 0xFE, 0xAB, 0x72,
95
+ 0xAD, 0x90, 0x77, 0xD5, 0x62, 0x5B, 0xAB, 0x12, 0x34, 0x9B,
96
+ 0x40, 0x0A, 0x4C, 0x03, 0xBC, 0x53
85
97
  };
86
- static unsigned char dh1024_g[] = { 0x02 };
98
+ static unsigned char dh2048_g[] = { 0x02 };
87
99
 
88
100
  DH *dh;
101
+ #if !(OPENSSL_VERSION_NUMBER < 0x10100005L)
102
+ BIGNUM *p, *g;
103
+ #endif
104
+
89
105
  dh = DH_new();
90
106
 
91
- #if OPENSSL_VERSION_NUMBER < 0x10100005L || defined(LIBRESSL_VERSION_NUMBER)
92
- dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
93
- dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
107
+ #if OPENSSL_VERSION_NUMBER < 0x10100005L
108
+ dh->p = BN_bin2bn(dh2048_p, sizeof(dh2048_p), NULL);
109
+ dh->g = BN_bin2bn(dh2048_g, sizeof(dh2048_g), NULL);
94
110
 
95
111
  if ((dh->p == NULL) || (dh->g == NULL)) {
96
112
  DH_free(dh);
97
113
  return NULL;
98
114
  }
99
115
  #else
100
- BIGNUM *p, *g;
101
- p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
102
- g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
116
+ p = BN_bin2bn(dh2048_p, sizeof(dh2048_p), NULL);
117
+ g = BN_bin2bn(dh2048_g, sizeof(dh2048_g), NULL);
103
118
 
104
119
  if (p == NULL || g == NULL || !DH_set0_pqg(dh, p, NULL, g)) {
105
120
  DH_free(dh);
@@ -111,6 +126,38 @@ DH *get_dh1024() {
111
126
 
112
127
  return dh;
113
128
  }
129
+ #endif
130
+
131
+ static void
132
+ sslctx_free(void *ptr) {
133
+ SSL_CTX *ctx = ptr;
134
+ SSL_CTX_free(ctx);
135
+ }
136
+
137
+ static const rb_data_type_t sslctx_type = {
138
+ "MiniSSL/SSLContext",
139
+ {
140
+ 0, sslctx_free,
141
+ },
142
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
143
+ };
144
+
145
+ ms_conn* engine_alloc(VALUE klass, VALUE* obj) {
146
+ ms_conn* conn;
147
+
148
+ *obj = TypedData_Make_Struct(klass, ms_conn, &engine_data_type, conn);
149
+
150
+ conn->read = BIO_new(BIO_s_mem());
151
+ BIO_set_nbio(conn->read, 1);
152
+
153
+ conn->write = BIO_new(BIO_s_mem());
154
+ BIO_set_nbio(conn->write, 1);
155
+
156
+ conn->ssl = 0;
157
+ conn->ctx = 0;
158
+
159
+ return conn;
160
+ }
114
161
 
115
162
  static int engine_verify_callback(int preverify_ok, X509_STORE_CTX* ctx) {
116
163
  X509* err_cert;
@@ -138,52 +185,129 @@ static int engine_verify_callback(int preverify_ok, X509_STORE_CTX* ctx) {
138
185
  return preverify_ok;
139
186
  }
140
187
 
141
- VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) {
142
- VALUE obj;
188
+ static VALUE
189
+ sslctx_alloc(VALUE klass) {
190
+ SSL_CTX *ctx;
191
+ long mode = 0 |
192
+ SSL_MODE_ENABLE_PARTIAL_WRITE |
193
+ SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
194
+ SSL_MODE_RELEASE_BUFFERS;
195
+
196
+ #ifdef HAVE_TLS_SERVER_METHOD
197
+ ctx = SSL_CTX_new(TLS_method());
198
+ // printf("\nctx using TLS_method security_level %d\n", SSL_CTX_get_security_level(ctx));
199
+ #else
200
+ ctx = SSL_CTX_new(SSLv23_method());
201
+ #endif
202
+ if (!ctx) {
203
+ rb_raise(eError, "SSL_CTX_new");
204
+ }
205
+ SSL_CTX_set_mode(ctx, mode);
206
+
207
+ return TypedData_Wrap_Struct(klass, &sslctx_type, ctx);
208
+ }
209
+
210
+ VALUE
211
+ sslctx_initialize(VALUE self, VALUE mini_ssl_ctx) {
143
212
  SSL_CTX* ctx;
144
- SSL* ssl;
145
- int min, ssl_options;
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;
146
230
 
147
- 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
148
235
 
149
- ID sym_key = rb_intern("key");
150
- VALUE key = rb_funcall(mini_ssl_ctx, sym_key, 0);
236
+ key = rb_funcall(mini_ssl_ctx, rb_intern_const("key"), 0);
151
237
 
152
- StringValue(key);
238
+ cert = rb_funcall(mini_ssl_ctx, rb_intern_const("cert"), 0);
153
239
 
154
- ID sym_cert = rb_intern("cert");
155
- VALUE cert = rb_funcall(mini_ssl_ctx, sym_cert, 0);
240
+ ca = rb_funcall(mini_ssl_ctx, rb_intern_const("ca"), 0);
156
241
 
157
- StringValue(cert);
242
+ cert_pem = rb_funcall(mini_ssl_ctx, rb_intern_const("cert_pem"), 0);
158
243
 
159
- ID sym_ca = rb_intern("ca");
160
- VALUE ca = rb_funcall(mini_ssl_ctx, sym_ca, 0);
244
+ key_pem = rb_funcall(mini_ssl_ctx, rb_intern_const("key_pem"), 0);
161
245
 
162
- ID sym_verify_mode = rb_intern("verify_mode");
163
- 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);
164
247
 
165
- ID sym_ssl_cipher_filter = rb_intern("ssl_cipher_filter");
166
- VALUE ssl_cipher_filter = rb_funcall(mini_ssl_ctx, sym_ssl_cipher_filter, 0);
248
+ ssl_cipher_filter = rb_funcall(mini_ssl_ctx, rb_intern_const("ssl_cipher_filter"), 0);
167
249
 
168
- ID sym_no_tlsv1 = rb_intern("no_tlsv1");
169
- 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);
170
251
 
171
- ID sym_no_tlsv1_1 = rb_intern("no_tlsv1_1");
172
- VALUE no_tlsv1_1 = rb_funcall(mini_ssl_ctx, sym_no_tlsv1_1, 0);
252
+ no_tlsv1_1 = rb_funcall(mini_ssl_ctx, rb_intern_const("no_tlsv1_1"), 0);
173
253
 
174
- #ifdef HAVE_TLS_SERVER_METHOD
175
- ctx = SSL_CTX_new(TLS_server_method());
176
- #else
177
- ctx = SSL_CTX_new(SSLv23_server_method());
178
- #endif
179
- conn->ctx = ctx;
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
+ }
180
284
 
181
- SSL_CTX_use_certificate_chain_file(ctx, RSTRING_PTR(cert));
182
- SSL_CTX_use_PrivateKey_file(ctx, RSTRING_PTR(key), SSL_FILETYPE_PEM);
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
+ }
183
305
 
184
306
  if (!NIL_P(ca)) {
185
307
  StringValue(ca);
186
- 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
+ }
187
311
  }
188
312
 
189
313
  ssl_options = SSL_OP_CIPHER_SERVER_PREFERENCE | SSL_OP_SINGLE_ECDH_USE | SSL_OP_NO_COMPRESSION;
@@ -198,10 +322,8 @@ VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) {
198
322
  else {
199
323
  min = TLS1_VERSION;
200
324
  }
201
-
202
- SSL_CTX_set_min_proto_version(ctx, min);
203
325
 
204
- SSL_CTX_set_options(ctx, ssl_options);
326
+ SSL_CTX_set_min_proto_version(ctx, min);
205
327
 
206
328
  #else
207
329
  /* As of 1.0.2f, SSL_OP_SINGLE_DH_USE key use is always on */
@@ -213,10 +335,23 @@ VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) {
213
335
  if(RTEST(no_tlsv1_1)) {
214
336
  ssl_options |= SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1;
215
337
  }
216
- SSL_CTX_set_options(ctx, ssl_options);
217
338
  #endif
218
339
 
219
- 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);
220
355
 
221
356
  if (!NIL_P(ssl_cipher_filter)) {
222
357
  StringValue(ssl_cipher_filter);
@@ -226,35 +361,65 @@ VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) {
226
361
  SSL_CTX_set_cipher_list(ctx, "HIGH:!aNULL@STRENGTH");
227
362
  }
228
363
 
229
- DH *dh = get_dh1024();
230
- SSL_CTX_set_tmp_dh(ctx, dh);
231
-
232
364
  #if OPENSSL_VERSION_NUMBER < 0x10002000L
233
- // Remove this case if OpenSSL 1.0.1 (now EOL) support is no
234
- // longer needed.
235
- EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
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);
236
367
  if (ecdh) {
237
368
  SSL_CTX_set_tmp_ecdh(ctx, ecdh);
238
369
  EC_KEY_free(ecdh);
239
370
  }
240
371
  #elif OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
241
- // Prior to OpenSSL 1.1.0, servers must manually enable server-side ECDH
242
- // negotiation.
243
372
  SSL_CTX_set_ecdh_auto(ctx, 1);
244
373
  #endif
245
374
 
246
- ssl = SSL_new(ctx);
247
- conn->ssl = ssl;
248
- SSL_set_app_data(ssl, NULL);
249
-
250
375
  if (NIL_P(verify_mode)) {
251
- /* SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL); */
376
+ /* SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); */
252
377
  } else {
253
- SSL_set_verify(ssl, NUM2INT(verify_mode), engine_verify_callback);
378
+ SSL_CTX_set_verify(ctx, NUM2INT(verify_mode), engine_verify_callback);
254
379
  }
255
380
 
256
- 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);
257
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
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);
258
423
  SSL_set_accept_state(ssl);
259
424
  return obj;
260
425
  }
@@ -281,7 +446,7 @@ VALUE engine_inject(VALUE self, VALUE str) {
281
446
  ms_conn* conn;
282
447
  long used;
283
448
 
284
- Data_Get_Struct(self, ms_conn, conn);
449
+ TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
285
450
 
286
451
  StringValue(str);
287
452
 
@@ -294,13 +459,14 @@ VALUE engine_inject(VALUE self, VALUE str) {
294
459
  return INT2FIX(used);
295
460
  }
296
461
 
297
- static VALUE eError;
462
+ NORETURN(void raise_error(SSL* ssl, int result));
298
463
 
299
464
  void raise_error(SSL* ssl, int result) {
300
465
  char buf[512];
301
466
  char msg[512];
302
467
  const char* err_str;
303
468
  int err = errno;
469
+ int mask = 4095;
304
470
  int ssl_err = SSL_get_error(ssl, result);
305
471
  int verify_err = (int) SSL_get_verify_result(ssl);
306
472
 
@@ -317,8 +483,7 @@ void raise_error(SSL* ssl, int result) {
317
483
  } else {
318
484
  err = (int) ERR_get_error();
319
485
  ERR_error_string_n(err, buf, sizeof(buf));
320
- snprintf(msg, sizeof(msg), "OpenSSL error: %s - %d", buf, err);
321
-
486
+ snprintf(msg, sizeof(msg), "OpenSSL error: %s - %d", buf, err & mask);
322
487
  }
323
488
  } else {
324
489
  snprintf(msg, sizeof(msg), "Unknown OpenSSL error: %d", ssl_err);
@@ -333,7 +498,7 @@ VALUE engine_read(VALUE self) {
333
498
  char buf[512];
334
499
  int bytes, error;
335
500
 
336
- Data_Get_Struct(self, ms_conn, conn);
501
+ TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
337
502
 
338
503
  ERR_clear_error();
339
504
 
@@ -360,7 +525,7 @@ VALUE engine_write(VALUE self, VALUE str) {
360
525
  ms_conn* conn;
361
526
  int bytes;
362
527
 
363
- Data_Get_Struct(self, ms_conn, conn);
528
+ TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
364
529
 
365
530
  StringValue(str);
366
531
 
@@ -382,9 +547,11 @@ VALUE engine_extract(VALUE self) {
382
547
  ms_conn* conn;
383
548
  int bytes;
384
549
  size_t pending;
385
- 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];
386
553
 
387
- Data_Get_Struct(self, ms_conn, conn);
554
+ TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
388
555
 
389
556
  pending = BIO_pending(conn->write);
390
557
  if(pending > 0) {
@@ -403,7 +570,7 @@ VALUE engine_shutdown(VALUE self) {
403
570
  ms_conn* conn;
404
571
  int ok;
405
572
 
406
- Data_Get_Struct(self, ms_conn, conn);
573
+ TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
407
574
 
408
575
  ERR_clear_error();
409
576
 
@@ -418,7 +585,7 @@ VALUE engine_shutdown(VALUE self) {
418
585
  VALUE engine_init(VALUE self) {
419
586
  ms_conn* conn;
420
587
 
421
- Data_Get_Struct(self, ms_conn, conn);
588
+ TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
422
589
 
423
590
  return SSL_in_init(conn->ssl) ? Qtrue : Qfalse;
424
591
  }
@@ -431,9 +598,13 @@ VALUE engine_peercert(VALUE self) {
431
598
  ms_cert_buf* cert_buf = NULL;
432
599
  VALUE rb_cert_buf;
433
600
 
434
- Data_Get_Struct(self, ms_conn, conn);
601
+ TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
435
602
 
603
+ #ifdef HAVE_SSL_GET1_PEER_CERTIFICATE
604
+ cert = SSL_get1_peer_certificate(conn->ssl);
605
+ #else
436
606
  cert = SSL_get_peer_certificate(conn->ssl);
607
+ #endif
437
608
  if(!cert) {
438
609
  /*
439
610
  * See if there was a failed certificate associated with this client.
@@ -462,12 +633,22 @@ VALUE engine_peercert(VALUE self) {
462
633
  return rb_cert_buf;
463
634
  }
464
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
+
465
646
  VALUE noop(VALUE self) {
466
647
  return Qnil;
467
648
  }
468
649
 
469
650
  void Init_mini_ssl(VALUE puma) {
470
- VALUE mod, eng;
651
+ VALUE mod, eng, sslctx;
471
652
 
472
653
  /* Fake operation for documentation (RDoc, YARD) */
473
654
  #if 0 == 1
@@ -480,7 +661,15 @@ void Init_mini_ssl(VALUE puma) {
480
661
  ERR_load_crypto_strings();
481
662
 
482
663
  mod = rb_define_module_under(puma, "MiniSSL");
664
+
483
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
+
484
673
 
485
674
  // OpenSSL Build / Runtime/Load versions
486
675
 
@@ -493,27 +682,27 @@ void Init_mini_ssl(VALUE puma) {
493
682
  #else
494
683
  rb_define_const(mod, "OPENSSL_LIBRARY_VERSION", rb_str_new2(SSLeay_version(SSLEAY_VERSION)));
495
684
  #endif
496
-
497
- #if defined(OPENSSL_NO_SSL3) || defined(OPENSSL_NO_SSL3_METHOD)
498
- /* True if SSL3 is not available */
499
- rb_define_const(mod, "OPENSSL_NO_SSL3", Qtrue);
500
- #else
501
- rb_define_const(mod, "OPENSSL_NO_SSL3", Qfalse);
502
- #endif
503
-
504
- #if defined(OPENSSL_NO_TLS1) || defined(OPENSSL_NO_TLS1_METHOD)
505
- /* True if TLS1 is not available */
506
- rb_define_const(mod, "OPENSSL_NO_TLS1", Qtrue);
507
- #else
508
- rb_define_const(mod, "OPENSSL_NO_TLS1", Qfalse);
509
- #endif
510
-
511
- #if defined(OPENSSL_NO_TLS1_1) || defined(OPENSSL_NO_TLS1_1_METHOD)
512
- /* True if TLS1_1 is not available */
513
- rb_define_const(mod, "OPENSSL_NO_TLS1_1", Qtrue);
514
- #else
515
- rb_define_const(mod, "OPENSSL_NO_TLS1_1", Qfalse);
516
- #endif
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);
689
+ #else
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);
705
+ #endif
517
706
 
518
707
  rb_define_singleton_method(mod, "check", noop, 0);
519
708
 
@@ -533,13 +722,16 @@ void Init_mini_ssl(VALUE puma) {
533
722
  rb_define_method(eng, "init?", engine_init, 0);
534
723
 
535
724
  rb_define_method(eng, "peercert", engine_peercert, 0);
725
+
726
+ rb_define_method(eng, "ssl_vers_st", engine_ssl_vers_st, 0);
536
727
  }
537
728
 
538
729
  #else
539
730
 
731
+ NORETURN(VALUE raise_error(VALUE self));
732
+
540
733
  VALUE raise_error(VALUE self) {
541
734
  rb_raise(rb_eStandardError, "SSL not available in this build");
542
- return Qnil;
543
735
  }
544
736
 
545
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
+ }