puma 3.12.1 → 5.6.7

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 (94) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +1608 -447
  3. data/LICENSE +23 -20
  4. data/README.md +175 -63
  5. data/bin/puma-wild +3 -9
  6. data/docs/architecture.md +59 -21
  7. data/docs/compile_options.md +21 -0
  8. data/docs/deployment.md +69 -58
  9. data/docs/fork_worker.md +33 -0
  10. data/docs/jungle/README.md +9 -0
  11. data/{tools → docs}/jungle/rc.d/README.md +1 -1
  12. data/{tools → docs}/jungle/rc.d/puma +2 -2
  13. data/docs/kubernetes.md +66 -0
  14. data/docs/nginx.md +1 -1
  15. data/docs/plugins.md +22 -12
  16. data/docs/rails_dev_mode.md +28 -0
  17. data/docs/restart.md +47 -22
  18. data/docs/signals.md +13 -11
  19. data/docs/stats.md +142 -0
  20. data/docs/systemd.md +95 -120
  21. data/ext/puma_http11/PumaHttp11Service.java +2 -2
  22. data/ext/puma_http11/ext_help.h +1 -1
  23. data/ext/puma_http11/extconf.rb +57 -2
  24. data/ext/puma_http11/http11_parser.c +105 -117
  25. data/ext/puma_http11/http11_parser.h +1 -1
  26. data/ext/puma_http11/http11_parser.java.rl +22 -38
  27. data/ext/puma_http11/http11_parser.rl +4 -2
  28. data/ext/puma_http11/http11_parser_common.rl +4 -4
  29. data/ext/puma_http11/mini_ssl.c +339 -98
  30. data/ext/puma_http11/no_ssl/PumaHttp11Service.java +15 -0
  31. data/ext/puma_http11/org/jruby/puma/Http11.java +108 -116
  32. data/ext/puma_http11/org/jruby/puma/Http11Parser.java +84 -99
  33. data/ext/puma_http11/org/jruby/puma/MiniSSL.java +124 -71
  34. data/ext/puma_http11/puma_http11.c +35 -51
  35. data/lib/puma/app/status.rb +71 -49
  36. data/lib/puma/binder.rb +234 -137
  37. data/lib/puma/cli.rb +28 -18
  38. data/lib/puma/client.rb +350 -230
  39. data/lib/puma/cluster/worker.rb +173 -0
  40. data/lib/puma/cluster/worker_handle.rb +94 -0
  41. data/lib/puma/cluster.rb +247 -232
  42. data/lib/puma/commonlogger.rb +2 -2
  43. data/lib/puma/configuration.rb +61 -51
  44. data/lib/puma/const.rb +42 -21
  45. data/lib/puma/control_cli.rb +115 -67
  46. data/lib/puma/detect.rb +29 -2
  47. data/lib/puma/dsl.rb +619 -123
  48. data/lib/puma/error_logger.rb +104 -0
  49. data/lib/puma/events.rb +55 -31
  50. data/lib/puma/io_buffer.rb +7 -5
  51. data/lib/puma/jruby_restart.rb +0 -58
  52. data/lib/puma/json_serialization.rb +96 -0
  53. data/lib/puma/launcher.rb +193 -69
  54. data/lib/puma/minissl/context_builder.rb +81 -0
  55. data/lib/puma/minissl.rb +170 -65
  56. data/lib/puma/null_io.rb +18 -1
  57. data/lib/puma/plugin/tmp_restart.rb +2 -0
  58. data/lib/puma/plugin.rb +7 -13
  59. data/lib/puma/queue_close.rb +26 -0
  60. data/lib/puma/rack/builder.rb +3 -5
  61. data/lib/puma/rack/urlmap.rb +2 -0
  62. data/lib/puma/rack_default.rb +2 -0
  63. data/lib/puma/reactor.rb +85 -316
  64. data/lib/puma/request.rb +476 -0
  65. data/lib/puma/runner.rb +48 -55
  66. data/lib/puma/server.rb +305 -695
  67. data/lib/puma/single.rb +11 -67
  68. data/lib/puma/state_file.rb +48 -8
  69. data/lib/puma/systemd.rb +46 -0
  70. data/lib/puma/thread_pool.rb +132 -82
  71. data/lib/puma/util.rb +33 -10
  72. data/lib/puma.rb +56 -0
  73. data/lib/rack/handler/puma.rb +5 -6
  74. data/lib/rack/version_restriction.rb +15 -0
  75. data/tools/Dockerfile +16 -0
  76. data/tools/trickletest.rb +0 -1
  77. metadata +46 -29
  78. data/ext/puma_http11/io_buffer.c +0 -155
  79. data/lib/puma/accept_nonblock.rb +0 -23
  80. data/lib/puma/compat.rb +0 -14
  81. data/lib/puma/convenient.rb +0 -25
  82. data/lib/puma/daemon_ext.rb +0 -33
  83. data/lib/puma/delegation.rb +0 -13
  84. data/lib/puma/java_io_buffer.rb +0 -47
  85. data/lib/puma/rack/backports/uri/common_193.rb +0 -33
  86. data/lib/puma/tcp_logger.rb +0 -41
  87. data/tools/jungle/README.md +0 -19
  88. data/tools/jungle/init.d/README.md +0 -61
  89. data/tools/jungle/init.d/puma +0 -421
  90. data/tools/jungle/init.d/run-puma +0 -18
  91. data/tools/jungle/upstart/README.md +0 -61
  92. data/tools/jungle/upstart/puma-manager.conf +0 -31
  93. data/tools/jungle/upstart/puma.conf +0 -69
  94. /data/{tools → docs}/jungle/rc.d/puma.conf +0 -0
@@ -1,5 +1,5 @@
1
1
  %%{
2
-
2
+
3
3
  machine puma_parser_common;
4
4
 
5
5
  #### HTTP PROTOCOL GRAMMAR
@@ -16,7 +16,7 @@
16
16
  unreserved = (alpha | digit | safe | extra | national);
17
17
  escape = ("%" xdigit xdigit);
18
18
  uchar = (unreserved | escape | "%");
19
- pchar = (uchar | ":" | "@" | "&" | "=" | "+");
19
+ pchar = (uchar | ":" | "@" | "&" | "=" | "+" | ";");
20
20
  tspecials = ("(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\\" | "\"" | "/" | "[" | "]" | "?" | "=" | "{" | "}" | " " | "\t");
21
21
 
22
22
  # elements
@@ -30,7 +30,7 @@
30
30
  query = ( uchar | reserved )* %query_string ;
31
31
  param = ( pchar | "/" )* ;
32
32
  params = ( param ( ";" param )* ) ;
33
- rel_path = ( path? %request_path (";" params)? ) ("?" %start_query query)?;
33
+ rel_path = ( path? %request_path ) ("?" %start_query query)?;
34
34
  absolute_path = ( "/"+ rel_path );
35
35
 
36
36
  Request_URI = ( "*" | absolute_uri | absolute_path ) >mark %request_uri;
@@ -43,7 +43,7 @@
43
43
 
44
44
  field_name = ( token -- ":" )+ >start_field $snake_upcase_field %write_field;
45
45
 
46
- field_value = any* >start_value %write_value;
46
+ field_value = ( (any -- CTL) | "\t" )* >start_value %write_value;
47
47
 
48
48
  message_header = field_name ":" " "* field_value :> CRLF;
49
49
 
@@ -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,44 +185,150 @@ 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
213
 
146
- ms_conn* conn = engine_alloc(self, &obj);
214
+ #ifdef HAVE_SSL_CTX_SET_MIN_PROTO_VERSION
215
+ int min;
216
+ #endif
217
+ int ssl_options;
218
+ VALUE key, cert, ca, verify_mode, ssl_cipher_filter, no_tlsv1, no_tlsv1_1,
219
+ verification_flags, session_id_bytes, cert_pem, key_pem;
220
+ #ifndef HAVE_SSL_CTX_SET_DH_AUTO
221
+ DH *dh;
222
+ #endif
223
+ BIO *bio;
224
+ X509 *x509;
225
+ EVP_PKEY *pkey;
226
+
227
+ #if OPENSSL_VERSION_NUMBER < 0x10002000L
228
+ EC_KEY *ecdh;
229
+ #endif
230
+
231
+ TypedData_Get_Struct(self, SSL_CTX, &sslctx_type, ctx);
232
+
233
+ key = rb_funcall(mini_ssl_ctx, rb_intern_const("key"), 0);
234
+
235
+ cert = rb_funcall(mini_ssl_ctx, rb_intern_const("cert"), 0);
236
+
237
+ ca = rb_funcall(mini_ssl_ctx, rb_intern_const("ca"), 0);
238
+
239
+ cert_pem = rb_funcall(mini_ssl_ctx, rb_intern_const("cert_pem"), 0);
240
+
241
+ key_pem = rb_funcall(mini_ssl_ctx, rb_intern_const("key_pem"), 0);
147
242
 
148
- ID sym_key = rb_intern("key");
149
- VALUE key = rb_funcall(mini_ssl_ctx, sym_key, 0);
243
+ verify_mode = rb_funcall(mini_ssl_ctx, rb_intern_const("verify_mode"), 0);
150
244
 
151
- StringValue(key);
245
+ ssl_cipher_filter = rb_funcall(mini_ssl_ctx, rb_intern_const("ssl_cipher_filter"), 0);
152
246
 
153
- ID sym_cert = rb_intern("cert");
154
- VALUE cert = rb_funcall(mini_ssl_ctx, sym_cert, 0);
247
+ no_tlsv1 = rb_funcall(mini_ssl_ctx, rb_intern_const("no_tlsv1"), 0);
155
248
 
156
- StringValue(cert);
249
+ no_tlsv1_1 = rb_funcall(mini_ssl_ctx, rb_intern_const("no_tlsv1_1"), 0);
157
250
 
158
- ID sym_ca = rb_intern("ca");
159
- VALUE ca = rb_funcall(mini_ssl_ctx, sym_ca, 0);
251
+ if (!NIL_P(cert)) {
252
+ StringValue(cert);
160
253
 
161
- ID sym_verify_mode = rb_intern("verify_mode");
162
- VALUE verify_mode = rb_funcall(mini_ssl_ctx, sym_verify_mode, 0);
254
+ if (SSL_CTX_use_certificate_chain_file(ctx, RSTRING_PTR(cert)) != 1) {
255
+ raise_file_error("SSL_CTX_use_certificate_chain_file", RSTRING_PTR(cert));
256
+ }
257
+ }
163
258
 
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);
259
+ if (!NIL_P(key)) {
260
+ StringValue(key);
166
261
 
167
- ctx = SSL_CTX_new(SSLv23_server_method());
168
- conn->ctx = ctx;
262
+ if (SSL_CTX_use_PrivateKey_file(ctx, RSTRING_PTR(key), SSL_FILETYPE_PEM) != 1) {
263
+ raise_file_error("SSL_CTX_use_PrivateKey_file", RSTRING_PTR(key));
264
+ }
265
+ }
169
266
 
170
- SSL_CTX_use_certificate_chain_file(ctx, RSTRING_PTR(cert));
171
- SSL_CTX_use_PrivateKey_file(ctx, RSTRING_PTR(key), SSL_FILETYPE_PEM);
267
+ if (!NIL_P(cert_pem)) {
268
+ bio = BIO_new(BIO_s_mem());
269
+ BIO_puts(bio, RSTRING_PTR(cert_pem));
270
+ x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
271
+
272
+ if (SSL_CTX_use_certificate(ctx, x509) != 1) {
273
+ raise_file_error("SSL_CTX_use_certificate", RSTRING_PTR(cert_pem));
274
+ }
275
+ }
276
+
277
+ if (!NIL_P(key_pem)) {
278
+ bio = BIO_new(BIO_s_mem());
279
+ BIO_puts(bio, RSTRING_PTR(key_pem));
280
+ pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
281
+
282
+ if (SSL_CTX_use_PrivateKey(ctx, pkey) != 1) {
283
+ raise_file_error("SSL_CTX_use_PrivateKey", RSTRING_PTR(key_pem));
284
+ }
285
+ }
286
+
287
+ verification_flags = rb_funcall(mini_ssl_ctx, rb_intern_const("verification_flags"), 0);
288
+
289
+ if (!NIL_P(verification_flags)) {
290
+ X509_VERIFY_PARAM *param = SSL_CTX_get0_param(ctx);
291
+ X509_VERIFY_PARAM_set_flags(param, NUM2INT(verification_flags));
292
+ SSL_CTX_set1_param(ctx, param);
293
+ }
172
294
 
173
295
  if (!NIL_P(ca)) {
174
296
  StringValue(ca);
175
- 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
+ }
176
300
  }
177
301
 
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);
302
+ ssl_options = SSL_OP_CIPHER_SERVER_PREFERENCE | SSL_OP_SINGLE_ECDH_USE | SSL_OP_NO_COMPRESSION;
303
+
304
+ #ifdef HAVE_SSL_CTX_SET_MIN_PROTO_VERSION
305
+ if (RTEST(no_tlsv1_1)) {
306
+ min = TLS1_2_VERSION;
307
+ }
308
+ else if (RTEST(no_tlsv1)) {
309
+ min = TLS1_1_VERSION;
310
+ }
311
+ else {
312
+ min = TLS1_VERSION;
313
+ }
314
+
315
+ SSL_CTX_set_min_proto_version(ctx, min);
316
+
317
+ SSL_CTX_set_options(ctx, ssl_options);
318
+
319
+ #else
320
+ /* As of 1.0.2f, SSL_OP_SINGLE_DH_USE key use is always on */
321
+ ssl_options |= SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_SINGLE_DH_USE;
322
+
323
+ if (RTEST(no_tlsv1)) {
324
+ ssl_options |= SSL_OP_NO_TLSv1;
325
+ }
326
+ if(RTEST(no_tlsv1_1)) {
327
+ ssl_options |= SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1;
328
+ }
329
+ SSL_CTX_set_options(ctx, ssl_options);
330
+ #endif
331
+
179
332
  SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
180
333
 
181
334
  if (!NIL_P(ssl_cipher_filter)) {
@@ -186,29 +339,66 @@ VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) {
186
339
  SSL_CTX_set_cipher_list(ctx, "HIGH:!aNULL@STRENGTH");
187
340
  }
188
341
 
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);
342
+ #if OPENSSL_VERSION_NUMBER < 0x10002000L
343
+ // Remove this case if OpenSSL 1.0.1 (now EOL) support is no
344
+ // longer needed.
345
+ ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
194
346
  if (ecdh) {
195
347
  SSL_CTX_set_tmp_ecdh(ctx, ecdh);
196
348
  EC_KEY_free(ecdh);
197
349
  }
350
+ #elif OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
351
+ SSL_CTX_set_ecdh_auto(ctx, 1);
198
352
  #endif
199
353
 
200
- ssl = SSL_new(ctx);
201
- conn->ssl = ssl;
202
- SSL_set_app_data(ssl, NULL);
203
-
204
354
  if (NIL_P(verify_mode)) {
205
- /* SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL); */
355
+ /* SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); */
206
356
  } else {
207
- SSL_set_verify(ssl, NUM2INT(verify_mode), engine_verify_callback);
357
+ SSL_CTX_set_verify(ctx, NUM2INT(verify_mode), engine_verify_callback);
208
358
  }
209
359
 
210
- SSL_set_bio(ssl, conn->read, conn->write);
360
+ // Random.bytes available in Ruby 2.5 and later, Random::DEFAULT deprecated in 3.0
361
+ session_id_bytes = rb_funcall(
362
+ #ifdef HAVE_RANDOM_BYTES
363
+ rb_cRandom,
364
+ #else
365
+ rb_const_get(rb_cRandom, rb_intern_const("DEFAULT")),
366
+ #endif
367
+ rb_intern_const("bytes"),
368
+ 1, ULL2NUM(SSL_MAX_SSL_SESSION_ID_LENGTH));
369
+
370
+ SSL_CTX_set_session_id_context(ctx,
371
+ (unsigned char *) RSTRING_PTR(session_id_bytes),
372
+ SSL_MAX_SSL_SESSION_ID_LENGTH);
373
+
374
+ // printf("\ninitialize end security_level %d\n", SSL_CTX_get_security_level(ctx));
375
+
376
+ #ifdef HAVE_SSL_CTX_SET_DH_AUTO
377
+ // https://www.openssl.org/docs/man3.0/man3/SSL_CTX_set_dh_auto.html
378
+ SSL_CTX_set_dh_auto(ctx, 1);
379
+ #else
380
+ dh = get_dh2048();
381
+ SSL_CTX_set_tmp_dh(ctx, dh);
382
+ #endif
383
+
384
+ rb_obj_freeze(self);
385
+ return self;
386
+ }
211
387
 
388
+ VALUE engine_init_server(VALUE self, VALUE sslctx) {
389
+ ms_conn* conn;
390
+ VALUE obj;
391
+ SSL_CTX* ctx;
392
+ SSL* ssl;
393
+
394
+ conn = engine_alloc(self, &obj);
395
+
396
+ TypedData_Get_Struct(sslctx, SSL_CTX, &sslctx_type, ctx);
397
+
398
+ ssl = SSL_new(ctx);
399
+ conn->ssl = ssl;
400
+ SSL_set_app_data(ssl, NULL);
401
+ SSL_set_bio(ssl, conn->read, conn->write);
212
402
  SSL_set_accept_state(ssl);
213
403
  return obj;
214
404
  }
@@ -216,8 +406,11 @@ VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) {
216
406
  VALUE engine_init_client(VALUE klass) {
217
407
  VALUE obj;
218
408
  ms_conn* conn = engine_alloc(klass, &obj);
219
-
409
+ #ifdef HAVE_DTLS_METHOD
410
+ conn->ctx = SSL_CTX_new(DTLS_method());
411
+ #else
220
412
  conn->ctx = SSL_CTX_new(DTLSv1_method());
413
+ #endif
221
414
  conn->ssl = SSL_new(conn->ctx);
222
415
  SSL_set_app_data(conn->ssl, NULL);
223
416
  SSL_set_verify(conn->ssl, SSL_VERIFY_NONE, NULL);
@@ -232,7 +425,7 @@ VALUE engine_inject(VALUE self, VALUE str) {
232
425
  ms_conn* conn;
233
426
  long used;
234
427
 
235
- Data_Get_Struct(self, ms_conn, conn);
428
+ TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
236
429
 
237
430
  StringValue(str);
238
431
 
@@ -245,13 +438,14 @@ VALUE engine_inject(VALUE self, VALUE str) {
245
438
  return INT2FIX(used);
246
439
  }
247
440
 
248
- static VALUE eError;
441
+ NORETURN(void raise_error(SSL* ssl, int result));
249
442
 
250
443
  void raise_error(SSL* ssl, int result) {
251
444
  char buf[512];
252
445
  char msg[512];
253
446
  const char* err_str;
254
447
  int err = errno;
448
+ int mask = 4095;
255
449
  int ssl_err = SSL_get_error(ssl, result);
256
450
  int verify_err = (int) SSL_get_verify_result(ssl);
257
451
 
@@ -268,8 +462,7 @@ void raise_error(SSL* ssl, int result) {
268
462
  } else {
269
463
  err = (int) ERR_get_error();
270
464
  ERR_error_string_n(err, buf, sizeof(buf));
271
- snprintf(msg, sizeof(msg), "OpenSSL error: %s - %d", buf, err);
272
-
465
+ snprintf(msg, sizeof(msg), "OpenSSL error: %s - %d", buf, err & mask);
273
466
  }
274
467
  } else {
275
468
  snprintf(msg, sizeof(msg), "Unknown OpenSSL error: %d", ssl_err);
@@ -284,7 +477,7 @@ VALUE engine_read(VALUE self) {
284
477
  char buf[512];
285
478
  int bytes, error;
286
479
 
287
- Data_Get_Struct(self, ms_conn, conn);
480
+ TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
288
481
 
289
482
  ERR_clear_error();
290
483
 
@@ -311,7 +504,7 @@ VALUE engine_write(VALUE self, VALUE str) {
311
504
  ms_conn* conn;
312
505
  int bytes;
313
506
 
314
- Data_Get_Struct(self, ms_conn, conn);
507
+ TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
315
508
 
316
509
  StringValue(str);
317
510
 
@@ -333,9 +526,11 @@ VALUE engine_extract(VALUE self) {
333
526
  ms_conn* conn;
334
527
  int bytes;
335
528
  size_t pending;
336
- char buf[512];
529
+ // https://www.openssl.org/docs/manmaster/man3/BIO_f_buffer.html
530
+ // crypto/bio/bf_buff.c DEFAULT_BUFFER_SIZE
531
+ char buf[4096];
337
532
 
338
- Data_Get_Struct(self, ms_conn, conn);
533
+ TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
339
534
 
340
535
  pending = BIO_pending(conn->write);
341
536
  if(pending > 0) {
@@ -354,7 +549,7 @@ VALUE engine_shutdown(VALUE self) {
354
549
  ms_conn* conn;
355
550
  int ok;
356
551
 
357
- Data_Get_Struct(self, ms_conn, conn);
552
+ TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
358
553
 
359
554
  ERR_clear_error();
360
555
 
@@ -369,7 +564,7 @@ VALUE engine_shutdown(VALUE self) {
369
564
  VALUE engine_init(VALUE self) {
370
565
  ms_conn* conn;
371
566
 
372
- Data_Get_Struct(self, ms_conn, conn);
567
+ TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
373
568
 
374
569
  return SSL_in_init(conn->ssl) ? Qtrue : Qfalse;
375
570
  }
@@ -382,9 +577,13 @@ VALUE engine_peercert(VALUE self) {
382
577
  ms_cert_buf* cert_buf = NULL;
383
578
  VALUE rb_cert_buf;
384
579
 
385
- Data_Get_Struct(self, ms_conn, conn);
580
+ TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
386
581
 
582
+ #ifdef HAVE_SSL_GET1_PEER_CERTIFICATE
583
+ cert = SSL_get1_peer_certificate(conn->ssl);
584
+ #else
387
585
  cert = SSL_get_peer_certificate(conn->ssl);
586
+ #endif
388
587
  if(!cert) {
389
588
  /*
390
589
  * See if there was a failed certificate associated with this client.
@@ -413,12 +612,22 @@ VALUE engine_peercert(VALUE self) {
413
612
  return rb_cert_buf;
414
613
  }
415
614
 
615
+ /* @see Puma::MiniSSL::Socket#ssl_version_state
616
+ * @version 5.0.0
617
+ */
618
+ static VALUE
619
+ engine_ssl_vers_st(VALUE self) {
620
+ ms_conn* conn;
621
+ TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
622
+ return rb_ary_new3(2, rb_str_new2(SSL_get_version(conn->ssl)), rb_str_new2(SSL_state_string(conn->ssl)));
623
+ }
624
+
416
625
  VALUE noop(VALUE self) {
417
626
  return Qnil;
418
627
  }
419
628
 
420
629
  void Init_mini_ssl(VALUE puma) {
421
- VALUE mod, eng;
630
+ VALUE mod, eng, sslctx;
422
631
 
423
632
  /* Fake operation for documentation (RDoc, YARD) */
424
633
  #if 0 == 1
@@ -431,18 +640,47 @@ void Init_mini_ssl(VALUE puma) {
431
640
  ERR_load_crypto_strings();
432
641
 
433
642
  mod = rb_define_module_under(puma, "MiniSSL");
643
+
434
644
  eng = rb_define_class_under(mod, "Engine", rb_cObject);
645
+ rb_undef_alloc_func(eng);
646
+
647
+ sslctx = rb_define_class_under(mod, "SSLContext", rb_cObject);
648
+ rb_define_alloc_func(sslctx, sslctx_alloc);
649
+ rb_define_method(sslctx, "initialize", sslctx_initialize, 1);
650
+ rb_undef_method(sslctx, "initialize_copy");
651
+
435
652
 
436
653
  // OpenSSL Build / Runtime/Load versions
437
654
 
438
655
  /* Version of OpenSSL that Puma was compiled with */
439
- rb_define_const(mod, "OPENSSL_VERSION", rb_str_new2(OPENSSL_VERSION_TEXT));
656
+ rb_define_const(mod, "OPENSSL_VERSION", rb_str_new2(OPENSSL_VERSION_TEXT));
440
657
 
441
658
  #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)));
659
+ /* Version of OpenSSL that Puma loaded with */
660
+ rb_define_const(mod, "OPENSSL_LIBRARY_VERSION", rb_str_new2(OpenSSL_version(OPENSSL_VERSION)));
661
+ #else
662
+ rb_define_const(mod, "OPENSSL_LIBRARY_VERSION", rb_str_new2(SSLeay_version(SSLEAY_VERSION)));
663
+ #endif
664
+
665
+ #if defined(OPENSSL_NO_SSL3) || defined(OPENSSL_NO_SSL3_METHOD)
666
+ /* True if SSL3 is not available */
667
+ rb_define_const(mod, "OPENSSL_NO_SSL3", Qtrue);
444
668
  #else
445
- rb_define_const(mod, "OPENSSL_LIBRARY_VERSION", rb_str_new2(SSLeay_version(SSLEAY_VERSION)));
669
+ rb_define_const(mod, "OPENSSL_NO_SSL3", Qfalse);
670
+ #endif
671
+
672
+ #if defined(OPENSSL_NO_TLS1) || defined(OPENSSL_NO_TLS1_METHOD)
673
+ /* True if TLS1 is not available */
674
+ rb_define_const(mod, "OPENSSL_NO_TLS1", Qtrue);
675
+ #else
676
+ rb_define_const(mod, "OPENSSL_NO_TLS1", Qfalse);
677
+ #endif
678
+
679
+ #if defined(OPENSSL_NO_TLS1_1) || defined(OPENSSL_NO_TLS1_1_METHOD)
680
+ /* True if TLS1_1 is not available */
681
+ rb_define_const(mod, "OPENSSL_NO_TLS1_1", Qtrue);
682
+ #else
683
+ rb_define_const(mod, "OPENSSL_NO_TLS1_1", Qfalse);
446
684
  #endif
447
685
 
448
686
  rb_define_singleton_method(mod, "check", noop, 0);
@@ -463,13 +701,16 @@ void Init_mini_ssl(VALUE puma) {
463
701
  rb_define_method(eng, "init?", engine_init, 0);
464
702
 
465
703
  rb_define_method(eng, "peercert", engine_peercert, 0);
704
+
705
+ rb_define_method(eng, "ssl_vers_st", engine_ssl_vers_st, 0);
466
706
  }
467
707
 
468
708
  #else
469
709
 
710
+ NORETURN(VALUE raise_error(VALUE self));
711
+
470
712
  VALUE raise_error(VALUE self) {
471
713
  rb_raise(rb_eStandardError, "SSL not available in this build");
472
- return Qnil;
473
714
  }
474
715
 
475
716
  void Init_mini_ssl(VALUE puma) {
@@ -0,0 +1,15 @@
1
+ package puma;
2
+
3
+ import java.io.IOException;
4
+
5
+ import org.jruby.Ruby;
6
+ import org.jruby.runtime.load.BasicLibraryService;
7
+
8
+ import org.jruby.puma.Http11;
9
+
10
+ public class PumaHttp11Service implements BasicLibraryService {
11
+ public boolean basicLoad(final Ruby runtime) throws IOException {
12
+ Http11.createHttp11(runtime);
13
+ return true;
14
+ }
15
+ }