puma 3.12.6 → 6.3.0
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.
- checksums.yaml +4 -4
- data/History.md +1806 -451
- data/LICENSE +23 -20
- data/README.md +217 -65
- data/bin/puma-wild +3 -9
- data/docs/architecture.md +59 -21
- data/docs/compile_options.md +55 -0
- data/docs/deployment.md +69 -58
- data/docs/fork_worker.md +31 -0
- data/docs/images/puma-connection-flow-no-reactor.png +0 -0
- data/docs/images/puma-connection-flow.png +0 -0
- data/docs/images/puma-general-arch.png +0 -0
- data/docs/jungle/README.md +9 -0
- data/{tools → docs}/jungle/rc.d/README.md +1 -1
- data/{tools → docs}/jungle/rc.d/puma +2 -2
- data/docs/kubernetes.md +66 -0
- data/docs/nginx.md +2 -2
- data/docs/plugins.md +22 -12
- data/docs/rails_dev_mode.md +28 -0
- data/docs/restart.md +47 -22
- data/docs/signals.md +13 -11
- data/docs/stats.md +142 -0
- data/docs/systemd.md +94 -120
- data/docs/testing_benchmarks_local_files.md +150 -0
- data/docs/testing_test_rackup_ci_files.md +36 -0
- data/ext/puma_http11/PumaHttp11Service.java +2 -2
- data/ext/puma_http11/ext_help.h +1 -1
- data/ext/puma_http11/extconf.rb +61 -3
- data/ext/puma_http11/http11_parser.c +103 -117
- data/ext/puma_http11/http11_parser.h +2 -2
- data/ext/puma_http11/http11_parser.java.rl +22 -38
- data/ext/puma_http11/http11_parser.rl +3 -3
- data/ext/puma_http11/http11_parser_common.rl +6 -6
- data/ext/puma_http11/mini_ssl.c +389 -99
- data/ext/puma_http11/no_ssl/PumaHttp11Service.java +15 -0
- data/ext/puma_http11/org/jruby/puma/Http11.java +108 -116
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +84 -99
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +248 -92
- data/ext/puma_http11/puma_http11.c +49 -57
- data/lib/puma/app/status.rb +71 -49
- data/lib/puma/binder.rb +244 -150
- data/lib/puma/cli.rb +38 -34
- data/lib/puma/client.rb +388 -244
- data/lib/puma/cluster/worker.rb +180 -0
- data/lib/puma/cluster/worker_handle.rb +97 -0
- data/lib/puma/cluster.rb +261 -243
- data/lib/puma/commonlogger.rb +21 -14
- data/lib/puma/configuration.rb +116 -88
- data/lib/puma/const.rb +154 -104
- data/lib/puma/control_cli.rb +115 -70
- data/lib/puma/detect.rb +33 -2
- data/lib/puma/dsl.rb +764 -134
- data/lib/puma/error_logger.rb +113 -0
- data/lib/puma/events.rb +16 -112
- data/lib/puma/io_buffer.rb +42 -5
- data/lib/puma/jruby_restart.rb +2 -59
- data/lib/puma/json_serialization.rb +96 -0
- data/lib/puma/launcher/bundle_pruner.rb +104 -0
- data/lib/puma/launcher.rb +184 -133
- data/lib/puma/log_writer.rb +147 -0
- data/lib/puma/minissl/context_builder.rb +93 -0
- data/lib/puma/minissl.rb +263 -70
- data/lib/puma/null_io.rb +18 -1
- data/lib/puma/plugin/systemd.rb +90 -0
- data/lib/puma/plugin/tmp_restart.rb +3 -1
- data/lib/puma/plugin.rb +7 -13
- data/lib/puma/rack/builder.rb +9 -11
- data/lib/puma/rack/urlmap.rb +2 -0
- data/lib/puma/rack_default.rb +21 -4
- data/lib/puma/reactor.rb +93 -315
- data/lib/puma/request.rb +671 -0
- data/lib/puma/runner.rb +94 -69
- data/lib/puma/sd_notify.rb +149 -0
- data/lib/puma/server.rb +327 -772
- data/lib/puma/single.rb +20 -74
- data/lib/puma/state_file.rb +45 -8
- data/lib/puma/thread_pool.rb +146 -92
- data/lib/puma/util.rb +22 -10
- data/lib/puma.rb +60 -5
- data/lib/rack/handler/puma.rb +116 -90
- data/tools/Dockerfile +16 -0
- data/tools/trickletest.rb +0 -1
- metadata +54 -32
- data/ext/puma_http11/io_buffer.c +0 -155
- data/lib/puma/accept_nonblock.rb +0 -23
- data/lib/puma/compat.rb +0 -14
- data/lib/puma/convenient.rb +0 -25
- data/lib/puma/daemon_ext.rb +0 -33
- data/lib/puma/delegation.rb +0 -13
- data/lib/puma/java_io_buffer.rb +0 -47
- data/lib/puma/rack/backports/uri/common_193.rb +0 -33
- data/lib/puma/tcp_logger.rb +0 -41
- data/tools/jungle/README.md +0 -19
- data/tools/jungle/init.d/README.md +0 -61
- data/tools/jungle/init.d/puma +0 -421
- data/tools/jungle/init.d/run-puma +0 -18
- data/tools/jungle/upstart/README.md +0 -61
- data/tools/jungle/upstart/puma-manager.conf +0 -31
- data/tools/jungle/upstart/puma.conf +0 -69
- /data/{tools → docs}/jungle/rc.d/puma.conf +0 -0
@@ -0,0 +1,93 @@
|
|
1
|
+
module Puma
|
2
|
+
module MiniSSL
|
3
|
+
class ContextBuilder
|
4
|
+
def initialize(params, log_writer)
|
5
|
+
@params = params
|
6
|
+
@log_writer = log_writer
|
7
|
+
end
|
8
|
+
|
9
|
+
def context
|
10
|
+
ctx = MiniSSL::Context.new
|
11
|
+
|
12
|
+
if defined?(JRUBY_VERSION)
|
13
|
+
unless params['keystore']
|
14
|
+
log_writer.error "Please specify the Java keystore via 'keystore='"
|
15
|
+
end
|
16
|
+
|
17
|
+
ctx.keystore = params['keystore']
|
18
|
+
|
19
|
+
unless params['keystore-pass']
|
20
|
+
log_writer.error "Please specify the Java keystore password via 'keystore-pass='"
|
21
|
+
end
|
22
|
+
|
23
|
+
ctx.keystore_pass = params['keystore-pass']
|
24
|
+
ctx.keystore_type = params['keystore-type']
|
25
|
+
|
26
|
+
if truststore = params['truststore']
|
27
|
+
ctx.truststore = truststore.eql?('default') ? :default : truststore
|
28
|
+
ctx.truststore_pass = params['truststore-pass']
|
29
|
+
ctx.truststore_type = params['truststore-type']
|
30
|
+
end
|
31
|
+
|
32
|
+
ctx.cipher_suites = params['cipher_suites'] || params['ssl_cipher_list']
|
33
|
+
ctx.protocols = params['protocols'] if params['protocols']
|
34
|
+
else
|
35
|
+
if params['key'].nil? && params['key_pem'].nil?
|
36
|
+
log_writer.error "Please specify the SSL key via 'key=' or 'key_pem='"
|
37
|
+
end
|
38
|
+
|
39
|
+
ctx.key = params['key'] if params['key']
|
40
|
+
ctx.key_pem = params['key_pem'] if params['key_pem']
|
41
|
+
ctx.key_password_command = params['key_password_command'] if params['key_password_command']
|
42
|
+
|
43
|
+
if params['cert'].nil? && params['cert_pem'].nil?
|
44
|
+
log_writer.error "Please specify the SSL cert via 'cert=' or 'cert_pem='"
|
45
|
+
end
|
46
|
+
|
47
|
+
ctx.cert = params['cert'] if params['cert']
|
48
|
+
ctx.cert_pem = params['cert_pem'] if params['cert_pem']
|
49
|
+
|
50
|
+
if ['peer', 'force_peer'].include?(params['verify_mode'])
|
51
|
+
unless params['ca']
|
52
|
+
log_writer.error "Please specify the SSL ca via 'ca='"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
ctx.ca = params['ca'] if params['ca']
|
57
|
+
ctx.ssl_cipher_filter = params['ssl_cipher_filter'] if params['ssl_cipher_filter']
|
58
|
+
|
59
|
+
ctx.reuse = params['reuse'] if params['reuse']
|
60
|
+
end
|
61
|
+
|
62
|
+
ctx.no_tlsv1 = params['no_tlsv1'] == 'true'
|
63
|
+
ctx.no_tlsv1_1 = params['no_tlsv1_1'] == 'true'
|
64
|
+
|
65
|
+
if params['verify_mode']
|
66
|
+
ctx.verify_mode = case params['verify_mode']
|
67
|
+
when "peer"
|
68
|
+
MiniSSL::VERIFY_PEER
|
69
|
+
when "force_peer"
|
70
|
+
MiniSSL::VERIFY_PEER | MiniSSL::VERIFY_FAIL_IF_NO_PEER_CERT
|
71
|
+
when "none"
|
72
|
+
MiniSSL::VERIFY_NONE
|
73
|
+
else
|
74
|
+
log_writer.error "Please specify a valid verify_mode="
|
75
|
+
MiniSSL::VERIFY_NONE
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
if params['verification_flags']
|
80
|
+
ctx.verification_flags = params['verification_flags'].split(',').
|
81
|
+
map { |flag| MiniSSL::VERIFICATION_FLAGS.fetch(flag) }.
|
82
|
+
inject { |sum, flag| sum ? sum | flag : flag }
|
83
|
+
end
|
84
|
+
|
85
|
+
ctx
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
attr_reader :params, :log_writer
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
data/lib/puma/minissl.rb
CHANGED
@@ -1,19 +1,33 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
begin
|
4
|
-
require 'io/wait'
|
5
|
-
|
4
|
+
require 'io/wait' unless Puma::HAS_NATIVE_IO_WAIT
|
5
|
+
rescue LoadError
|
6
6
|
end
|
7
7
|
|
8
|
+
require 'open3'
|
9
|
+
# need for Puma::MiniSSL::OPENSSL constants used in `HAS_TLS1_3`
|
10
|
+
# use require, see https://github.com/puma/puma/pull/2381
|
11
|
+
require 'puma/puma_http11'
|
12
|
+
|
8
13
|
module Puma
|
9
14
|
module MiniSSL
|
15
|
+
# Define constant at runtime, as it's easy to determine at built time,
|
16
|
+
# but Puma could (it shouldn't) be loaded with an older OpenSSL version
|
17
|
+
# @version 5.0.0
|
18
|
+
HAS_TLS1_3 = IS_JRUBY ||
|
19
|
+
((OPENSSL_VERSION[/ \d+\.\d+\.\d+/].split('.').map(&:to_i) <=> [1,1,1]) != -1 &&
|
20
|
+
(OPENSSL_LIBRARY_VERSION[/ \d+\.\d+\.\d+/].split('.').map(&:to_i) <=> [1,1,1]) !=-1)
|
21
|
+
|
10
22
|
class Socket
|
11
23
|
def initialize(socket, engine)
|
12
24
|
@socket = socket
|
13
25
|
@engine = engine
|
14
26
|
@peercert = nil
|
27
|
+
@reuse = nil
|
15
28
|
end
|
16
29
|
|
30
|
+
# @!attribute [r] to_io
|
17
31
|
def to_io
|
18
32
|
@socket
|
19
33
|
end
|
@@ -22,6 +36,27 @@ module Puma
|
|
22
36
|
@socket.closed?
|
23
37
|
end
|
24
38
|
|
39
|
+
# Returns a two element array,
|
40
|
+
# first is protocol version (SSL_get_version),
|
41
|
+
# second is 'handshake' state (SSL_state_string)
|
42
|
+
#
|
43
|
+
# Used for dropping tcp connections to ssl.
|
44
|
+
# See OpenSSL ssl/ssl_stat.c SSL_state_string for info
|
45
|
+
# @!attribute [r] ssl_version_state
|
46
|
+
# @version 5.0.0
|
47
|
+
#
|
48
|
+
def ssl_version_state
|
49
|
+
IS_JRUBY ? [nil, nil] : @engine.ssl_vers_st
|
50
|
+
end
|
51
|
+
|
52
|
+
# Used to check the handshake status, in particular when a TCP connection
|
53
|
+
# is made with TLSv1.3 as an available protocol
|
54
|
+
# @version 5.0.0
|
55
|
+
def bad_tlsv1_3?
|
56
|
+
HAS_TLS1_3 && ssl_version_state == ['TLSv1.3', 'SSLERR']
|
57
|
+
end
|
58
|
+
private :bad_tlsv1_3?
|
59
|
+
|
25
60
|
def readpartial(size)
|
26
61
|
while true
|
27
62
|
output = @engine.read
|
@@ -54,22 +89,22 @@ module Puma
|
|
54
89
|
output = engine_read_all
|
55
90
|
return output if output
|
56
91
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
end
|
92
|
+
data = @socket.read_nonblock(size, exception: false)
|
93
|
+
if data == :wait_readable || data == :wait_writable
|
94
|
+
# It would make more sense to let @socket.read_nonblock raise
|
95
|
+
# EAGAIN if necessary but it seems like it'll misbehave on Windows.
|
96
|
+
# I don't have a Windows machine to debug this so I can't explain
|
97
|
+
# exactly whats happening in that OS. Please let me know if you
|
98
|
+
# find out!
|
99
|
+
#
|
100
|
+
# In the meantime, we can emulate the correct behavior by
|
101
|
+
# capturing :wait_readable & :wait_writable and raising EAGAIN
|
102
|
+
# ourselves.
|
103
|
+
raise IO::EAGAINWaitReadable
|
104
|
+
elsif data.nil?
|
105
|
+
raise SSLError.exception "HTTP connection?" if bad_tlsv1_3?
|
106
|
+
return nil
|
107
|
+
end
|
73
108
|
|
74
109
|
@engine.inject(data)
|
75
110
|
output = engine_read_all
|
@@ -85,22 +120,23 @@ module Puma
|
|
85
120
|
def write(data)
|
86
121
|
return 0 if data.empty?
|
87
122
|
|
88
|
-
|
123
|
+
data_size = data.bytesize
|
124
|
+
need = data_size
|
89
125
|
|
90
126
|
while true
|
91
127
|
wrote = @engine.write data
|
92
|
-
enc = @engine.extract
|
93
128
|
|
94
|
-
|
95
|
-
|
96
|
-
|
129
|
+
enc_wr = +''
|
130
|
+
while (enc = @engine.extract)
|
131
|
+
enc_wr << enc
|
97
132
|
end
|
133
|
+
@socket.write enc_wr unless enc_wr.empty?
|
98
134
|
|
99
135
|
need -= wrote
|
100
136
|
|
101
|
-
return
|
137
|
+
return data_size if need == 0
|
102
138
|
|
103
|
-
data = data
|
139
|
+
data = data.byteslice(wrote..-1)
|
104
140
|
end
|
105
141
|
end
|
106
142
|
|
@@ -108,14 +144,18 @@ module Puma
|
|
108
144
|
alias_method :<<, :write
|
109
145
|
|
110
146
|
# This is a temporary fix to deal with websockets code using
|
111
|
-
# write_nonblock.
|
147
|
+
# write_nonblock.
|
148
|
+
|
149
|
+
# The problem with implementing it properly
|
112
150
|
# is that it means we'd have to have the ability to rewind
|
113
151
|
# an engine because after we write+extract, the socket
|
114
152
|
# write_nonblock call might raise an exception and later
|
115
153
|
# code would pass the same data in, but the engine would think
|
116
|
-
# it had already written the data in.
|
117
|
-
#
|
118
|
-
#
|
154
|
+
# it had already written the data in.
|
155
|
+
#
|
156
|
+
# So for the time being (and since write blocking is quite rare),
|
157
|
+
# go ahead and actually block in write_nonblock.
|
158
|
+
#
|
119
159
|
def write_nonblock(data, *_)
|
120
160
|
write data
|
121
161
|
end
|
@@ -124,39 +164,27 @@ module Puma
|
|
124
164
|
@socket.flush
|
125
165
|
end
|
126
166
|
|
127
|
-
def read_and_drop(timeout = 1)
|
128
|
-
return :timeout unless IO.select([@socket], nil, nil, timeout)
|
129
|
-
return :eof unless read_nonblock(1024)
|
130
|
-
:drop
|
131
|
-
rescue Errno::EAGAIN
|
132
|
-
# do nothing
|
133
|
-
:eagain
|
134
|
-
end
|
135
|
-
|
136
|
-
def should_drop_bytes?
|
137
|
-
@engine.init? || !@engine.shutdown
|
138
|
-
end
|
139
|
-
|
140
167
|
def close
|
141
168
|
begin
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
return if [:timeout, :eof].include?(read_and_drop(1))
|
169
|
+
unless @engine.shutdown
|
170
|
+
while alert_data = @engine.extract
|
171
|
+
@socket.write alert_data
|
172
|
+
end
|
147
173
|
end
|
148
174
|
rescue IOError, SystemCallError
|
149
|
-
|
175
|
+
Puma::Util.purge_interrupt_queue
|
150
176
|
# nothing
|
151
177
|
ensure
|
152
178
|
@socket.close
|
153
179
|
end
|
154
180
|
end
|
155
181
|
|
182
|
+
# @!attribute [r] peeraddr
|
156
183
|
def peeraddr
|
157
184
|
@socket.peeraddr
|
158
185
|
end
|
159
186
|
|
187
|
+
# @!attribute [r] peercert
|
160
188
|
def peercert
|
161
189
|
return @peercert if @peercert
|
162
190
|
|
@@ -167,94 +195,259 @@ module Puma
|
|
167
195
|
end
|
168
196
|
end
|
169
197
|
|
170
|
-
if
|
171
|
-
|
172
|
-
|
173
|
-
end
|
174
|
-
|
175
|
-
def self.check; end
|
198
|
+
if IS_JRUBY
|
199
|
+
OPENSSL_NO_SSL3 = false
|
200
|
+
OPENSSL_NO_TLS1 = false
|
176
201
|
end
|
177
202
|
|
178
203
|
class Context
|
179
204
|
attr_accessor :verify_mode
|
205
|
+
attr_reader :no_tlsv1, :no_tlsv1_1
|
206
|
+
|
207
|
+
def initialize
|
208
|
+
@no_tlsv1 = false
|
209
|
+
@no_tlsv1_1 = false
|
210
|
+
@key = nil
|
211
|
+
@cert = nil
|
212
|
+
@key_pem = nil
|
213
|
+
@cert_pem = nil
|
214
|
+
@reuse = nil
|
215
|
+
@reuse_cache_size = nil
|
216
|
+
@reuse_timeout = nil
|
217
|
+
end
|
180
218
|
|
181
|
-
|
219
|
+
def check_file(file, desc)
|
220
|
+
raise ArgumentError, "#{desc} file '#{file}' does not exist" unless File.exist? file
|
221
|
+
raise ArgumentError, "#{desc} file '#{file}' is not readable" unless File.readable? file
|
222
|
+
end
|
223
|
+
|
224
|
+
if IS_JRUBY
|
182
225
|
# jruby-specific Context properties: java uses a keystore and password pair rather than a cert/key pair
|
183
226
|
attr_reader :keystore
|
227
|
+
attr_reader :keystore_type
|
184
228
|
attr_accessor :keystore_pass
|
185
|
-
|
229
|
+
attr_reader :truststore
|
230
|
+
attr_reader :truststore_type
|
231
|
+
attr_accessor :truststore_pass
|
232
|
+
attr_reader :cipher_suites
|
233
|
+
attr_reader :protocols
|
186
234
|
|
187
235
|
def keystore=(keystore)
|
188
|
-
|
236
|
+
check_file keystore, 'Keystore'
|
189
237
|
@keystore = keystore
|
190
238
|
end
|
191
239
|
|
240
|
+
def truststore=(truststore)
|
241
|
+
# NOTE: historically truststore was assumed the same as keystore, this is kept for backwards
|
242
|
+
# compatibility, to rely on JVM's trust defaults we allow setting `truststore = :default`
|
243
|
+
unless truststore.eql?(:default)
|
244
|
+
raise ArgumentError, "No such truststore file '#{truststore}'" unless File.exist?(truststore)
|
245
|
+
end
|
246
|
+
@truststore = truststore
|
247
|
+
end
|
248
|
+
|
249
|
+
def keystore_type=(type)
|
250
|
+
raise ArgumentError, "Invalid keystore type: #{type.inspect}" unless ['pkcs12', 'jks', nil].include?(type)
|
251
|
+
@keystore_type = type
|
252
|
+
end
|
253
|
+
|
254
|
+
def truststore_type=(type)
|
255
|
+
raise ArgumentError, "Invalid truststore type: #{type.inspect}" unless ['pkcs12', 'jks', nil].include?(type)
|
256
|
+
@truststore_type = type
|
257
|
+
end
|
258
|
+
|
259
|
+
def cipher_suites=(list)
|
260
|
+
list = list.split(',').map(&:strip) if list.is_a?(String)
|
261
|
+
@cipher_suites = list
|
262
|
+
end
|
263
|
+
|
264
|
+
# aliases for backwards compatibility
|
265
|
+
alias_method :ssl_cipher_list, :cipher_suites
|
266
|
+
alias_method :ssl_cipher_list=, :cipher_suites=
|
267
|
+
|
268
|
+
def protocols=(list)
|
269
|
+
list = list.split(',').map(&:strip) if list.is_a?(String)
|
270
|
+
@protocols = list
|
271
|
+
end
|
272
|
+
|
192
273
|
def check
|
193
274
|
raise "Keystore not configured" unless @keystore
|
275
|
+
# @truststore defaults to @keystore due backwards compatibility
|
194
276
|
end
|
195
277
|
|
196
278
|
else
|
197
279
|
# non-jruby Context properties
|
198
280
|
attr_reader :key
|
281
|
+
attr_reader :key_password_command
|
199
282
|
attr_reader :cert
|
200
283
|
attr_reader :ca
|
284
|
+
attr_reader :cert_pem
|
285
|
+
attr_reader :key_pem
|
201
286
|
attr_accessor :ssl_cipher_filter
|
287
|
+
attr_accessor :verification_flags
|
288
|
+
|
289
|
+
attr_reader :reuse, :reuse_cache_size, :reuse_timeout
|
202
290
|
|
203
291
|
def key=(key)
|
204
|
-
|
292
|
+
check_file key, 'Key'
|
205
293
|
@key = key
|
206
294
|
end
|
207
295
|
|
296
|
+
def key_password_command=(key_password_command)
|
297
|
+
@key_password_command = key_password_command
|
298
|
+
end
|
299
|
+
|
208
300
|
def cert=(cert)
|
209
|
-
|
301
|
+
check_file cert, 'Cert'
|
210
302
|
@cert = cert
|
211
303
|
end
|
212
304
|
|
213
305
|
def ca=(ca)
|
214
|
-
|
306
|
+
check_file ca, 'ca'
|
215
307
|
@ca = ca
|
216
308
|
end
|
217
309
|
|
310
|
+
def cert_pem=(cert_pem)
|
311
|
+
raise ArgumentError, "'cert_pem' is not a String" unless cert_pem.is_a? String
|
312
|
+
@cert_pem = cert_pem
|
313
|
+
end
|
314
|
+
|
315
|
+
def key_pem=(key_pem)
|
316
|
+
raise ArgumentError, "'key_pem' is not a String" unless key_pem.is_a? String
|
317
|
+
@key_pem = key_pem
|
318
|
+
end
|
319
|
+
|
218
320
|
def check
|
219
|
-
raise "Key not configured"
|
220
|
-
raise "Cert not configured"
|
321
|
+
raise "Key not configured" if @key.nil? && @key_pem.nil?
|
322
|
+
raise "Cert not configured" if @cert.nil? && @cert_pem.nil?
|
323
|
+
end
|
324
|
+
|
325
|
+
# Executes the command to return the password needed to decrypt the key.
|
326
|
+
def key_password
|
327
|
+
raise "Key password command not configured" if @key_password_command.nil?
|
328
|
+
|
329
|
+
stdout_str, stderr_str, status = Open3.capture3(@key_password_command)
|
330
|
+
|
331
|
+
return stdout_str.chomp if status.success?
|
332
|
+
|
333
|
+
raise "Key password failed with code #{status.exitstatus}: #{stderr_str}"
|
221
334
|
end
|
335
|
+
|
336
|
+
# Controls session reuse. Allowed values are as follows:
|
337
|
+
# * 'off' - matches the behavior of Puma 5.6 and earlier. This is included
|
338
|
+
# in case reuse 'on' is made the default in future Puma versions.
|
339
|
+
# * 'dflt' - sets session reuse on, with OpenSSL default cache size of
|
340
|
+
# 20k and default timeout of 300 seconds.
|
341
|
+
# * 's,t' - where s and t are integer strings, for size and timeout.
|
342
|
+
# * 's' - where s is an integer strings for size.
|
343
|
+
# * ',t' - where t is an integer strings for timeout.
|
344
|
+
#
|
345
|
+
def reuse=(reuse_str)
|
346
|
+
case reuse_str
|
347
|
+
when 'off'
|
348
|
+
@reuse = nil
|
349
|
+
when 'dflt'
|
350
|
+
@reuse = true
|
351
|
+
when /\A\d+\z/
|
352
|
+
@reuse = true
|
353
|
+
@reuse_cache_size = reuse_str.to_i
|
354
|
+
when /\A\d+,\d+\z/
|
355
|
+
@reuse = true
|
356
|
+
size, time = reuse_str.split ','
|
357
|
+
@reuse_cache_size = size.to_i
|
358
|
+
@reuse_timeout = time.to_i
|
359
|
+
when /\A,\d+\z/
|
360
|
+
@reuse = true
|
361
|
+
@reuse_timeout = reuse_str.delete(',').to_i
|
362
|
+
end
|
363
|
+
end
|
364
|
+
end
|
365
|
+
|
366
|
+
# disables TLSv1
|
367
|
+
# @!attribute [w] no_tlsv1=
|
368
|
+
def no_tlsv1=(tlsv1)
|
369
|
+
raise ArgumentError, "Invalid value of no_tlsv1=" unless ['true', 'false', true, false].include?(tlsv1)
|
370
|
+
@no_tlsv1 = tlsv1
|
371
|
+
end
|
372
|
+
|
373
|
+
# disables TLSv1 and TLSv1.1. Overrides `#no_tlsv1=`
|
374
|
+
# @!attribute [w] no_tlsv1_1=
|
375
|
+
def no_tlsv1_1=(tlsv1_1)
|
376
|
+
raise ArgumentError, "Invalid value of no_tlsv1_1=" unless ['true', 'false', true, false].include?(tlsv1_1)
|
377
|
+
@no_tlsv1_1 = tlsv1_1
|
222
378
|
end
|
379
|
+
|
223
380
|
end
|
224
381
|
|
225
382
|
VERIFY_NONE = 0
|
226
383
|
VERIFY_PEER = 1
|
227
384
|
VERIFY_FAIL_IF_NO_PEER_CERT = 2
|
228
385
|
|
386
|
+
# https://github.com/openssl/openssl/blob/master/include/openssl/x509_vfy.h.in
|
387
|
+
# /* Certificate verify flags */
|
388
|
+
VERIFICATION_FLAGS = {
|
389
|
+
"USE_CHECK_TIME" => 0x2,
|
390
|
+
"CRL_CHECK" => 0x4,
|
391
|
+
"CRL_CHECK_ALL" => 0x8,
|
392
|
+
"IGNORE_CRITICAL" => 0x10,
|
393
|
+
"X509_STRICT" => 0x20,
|
394
|
+
"ALLOW_PROXY_CERTS" => 0x40,
|
395
|
+
"POLICY_CHECK" => 0x80,
|
396
|
+
"EXPLICIT_POLICY" => 0x100,
|
397
|
+
"INHIBIT_ANY" => 0x200,
|
398
|
+
"INHIBIT_MAP" => 0x400,
|
399
|
+
"NOTIFY_POLICY" => 0x800,
|
400
|
+
"EXTENDED_CRL_SUPPORT" => 0x1000,
|
401
|
+
"USE_DELTAS" => 0x2000,
|
402
|
+
"CHECK_SS_SIGNATURE" => 0x4000,
|
403
|
+
"TRUSTED_FIRST" => 0x8000,
|
404
|
+
"SUITEB_128_LOS_ONLY" => 0x10000,
|
405
|
+
"SUITEB_192_LOS" => 0x20000,
|
406
|
+
"SUITEB_128_LOS" => 0x30000,
|
407
|
+
"PARTIAL_CHAIN" => 0x80000,
|
408
|
+
"NO_ALT_CHAINS" => 0x100000,
|
409
|
+
"NO_CHECK_TIME" => 0x200000
|
410
|
+
}.freeze
|
411
|
+
|
229
412
|
class Server
|
230
413
|
def initialize(socket, ctx)
|
231
414
|
@socket = socket
|
232
415
|
@ctx = ctx
|
233
|
-
|
234
|
-
|
235
|
-
def to_io
|
236
|
-
@socket
|
416
|
+
@eng_ctx = IS_JRUBY ? @ctx : SSLContext.new(ctx)
|
237
417
|
end
|
238
418
|
|
239
419
|
def accept
|
240
420
|
@ctx.check
|
241
421
|
io = @socket.accept
|
242
|
-
engine = Engine.server @
|
243
|
-
|
422
|
+
engine = Engine.server @eng_ctx
|
244
423
|
Socket.new io, engine
|
245
424
|
end
|
246
425
|
|
247
426
|
def accept_nonblock
|
248
427
|
@ctx.check
|
249
428
|
io = @socket.accept_nonblock
|
250
|
-
engine = Engine.server @
|
251
|
-
|
429
|
+
engine = Engine.server @eng_ctx
|
252
430
|
Socket.new io, engine
|
253
431
|
end
|
254
432
|
|
433
|
+
# @!attribute [r] to_io
|
434
|
+
def to_io
|
435
|
+
@socket
|
436
|
+
end
|
437
|
+
|
438
|
+
# @!attribute [r] addr
|
439
|
+
# @version 5.0.0
|
440
|
+
def addr
|
441
|
+
@socket.addr
|
442
|
+
end
|
443
|
+
|
255
444
|
def close
|
256
445
|
@socket.close unless @socket.closed? # closed? call is for Windows
|
257
446
|
end
|
447
|
+
|
448
|
+
def closed?
|
449
|
+
@socket.closed?
|
450
|
+
end
|
258
451
|
end
|
259
452
|
end
|
260
453
|
end
|
data/lib/puma/null_io.rb
CHANGED
@@ -9,13 +9,17 @@ module Puma
|
|
9
9
|
nil
|
10
10
|
end
|
11
11
|
|
12
|
+
def string
|
13
|
+
""
|
14
|
+
end
|
15
|
+
|
12
16
|
def each
|
13
17
|
end
|
14
18
|
|
15
19
|
# Mimics IO#read with no data.
|
16
20
|
#
|
17
21
|
def read(count = nil, _buffer = nil)
|
18
|
-
|
22
|
+
count && count > 0 ? nil : ""
|
19
23
|
end
|
20
24
|
|
21
25
|
def rewind
|
@@ -32,6 +36,10 @@ module Puma
|
|
32
36
|
true
|
33
37
|
end
|
34
38
|
|
39
|
+
def sync
|
40
|
+
true
|
41
|
+
end
|
42
|
+
|
35
43
|
def sync=(v)
|
36
44
|
end
|
37
45
|
|
@@ -40,5 +48,14 @@ module Puma
|
|
40
48
|
|
41
49
|
def write(*ary)
|
42
50
|
end
|
51
|
+
|
52
|
+
def flush
|
53
|
+
self
|
54
|
+
end
|
55
|
+
|
56
|
+
# This is used as singleton class, so can't have state.
|
57
|
+
def closed?
|
58
|
+
false
|
59
|
+
end
|
43
60
|
end
|
44
61
|
end
|