tttls1.3 0.2.12 → 0.2.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9677aea746ca98f9d18cfc1e841d836291b7692088cea9fcc3122e88b0bcb32a
4
- data.tar.gz: e156e172215e1b76c45a4a43c85e6066499f65e0b0bf8a28c2d6fb524fd8940e
3
+ metadata.gz: d292d936d6b26ed1f6307bde684a4f982ea1ee2a7f287eeb306d33b048f855a3
4
+ data.tar.gz: ef33ef7ce5bd53425d7feb6d7ebf4bca2a3803cf50f930375a441cef0543ab0e
5
5
  SHA512:
6
- metadata.gz: f12cffcb976c740136afd8fa7b139400f58cb1a3795e7e7347192630e90b0c8e6c5138e9b98214bbc2a7f88a91ecd58332390ef1c1239ccf9d56a71f3f342743
7
- data.tar.gz: 5ab10fcdab0e5cac1c4940bb92753c06db1656f615a3146b552b54c119b28483388bbe8b725b8a412b13df0fa3f1f668eaebc7cfb537e10753a3f2e686cf2279
6
+ metadata.gz: 815f58f7d9d0d7c64911979b01304826601767d1397cdeda326856916b15f2d5c8e42b38379d91e9f720c29f2c71f6bdbe308d42e70428413fad345f553e1c42
7
+ data.tar.gz: fcffc6d40024429db1f4a4c5573b0680ce4fb603aa06d9876f274a202726e72078f538222cf0ea974a7bf444b11821350510fb7a89b1384c0bb25ce05ba7877f
@@ -11,15 +11,20 @@ on:
11
11
  jobs:
12
12
  ci:
13
13
  runs-on: ubuntu-latest
14
+ strategy:
15
+ matrix:
16
+ ruby-version: ['2.6.x']
14
17
  steps:
15
- - uses: actions/checkout@v1
16
- - uses: actions/setup-ruby@v1
17
18
  - uses: thekuwayama/openssl@master
18
- with:
19
- ruby-version: '2.6.x'
20
- - run: gem install bundler
21
- - run: bundle install
22
- - run: docker pull thekuwayama/openssl
23
- - run: bundle exec rake
24
- - run: bundle exec rake interop:client
25
- - run: bundle exec rake interop:server
19
+ - name: Set up Ruby
20
+ uses: actions/setup-ruby@v1
21
+ - uses: actions/checkout@v1
22
+ - name: Install dependencies
23
+ run: |
24
+ gem install bundler
25
+ bundle install
26
+ - name: Run test
27
+ run: |
28
+ bundle exec rake
29
+ bundle exec rake interop:client
30
+ bundle exec rake interop:server
@@ -16,7 +16,7 @@ Metrics/AbcSize:
16
16
  Metrics/MethodLength:
17
17
  Max: 30
18
18
 
19
- Naming/UncommunicativeMethodParamName:
19
+ Naming/MethodParameterName:
20
20
  MinNameLength: 1
21
21
 
22
22
  Metrics/BlockLength:
data/Gemfile CHANGED
@@ -10,7 +10,7 @@ group :test do
10
10
  gem 'pry'
11
11
  gem 'pry-byebug'
12
12
  gem 'rspec', '3.8.0'
13
- gem 'rubocop', '0.67.2'
13
+ gem 'rubocop', '0.78.0'
14
14
  end
15
15
 
16
16
  gemspec
data/README.md CHANGED
@@ -119,6 +119,7 @@ tttls1.3 server is configurable using keyword arguments.
119
119
  | `:signature_algorithms` | Array of TTTLS13::SignatureScheme constant | `ECDSA_SECP256R1_SHA256`, `ECDSA_SECP384R1_SHA384`, `ECDSA_SECP521R1_SHA512`, `RSA_PSS_RSAE_SHA256`, `RSA_PSS_RSAE_SHA384`, `RSA_PSS_RSAE_SHA512`, `RSA_PKCS1_SHA256`, `RSA_PKCS1_SHA384`, `RSA_PKCS1_SHA512` | List of supported signature algorithms. |
120
120
  | `:supported_groups` | Array of TTTLS13::NamedGroup constant | `SECP256R1`, `SECP384R1`, `SECP521R1` | List of supported named groups. |
121
121
  | `:alpn` | Array of String | nil | List of supported application protocols. If not needed to check this extension, set nil. |
122
+ | `:process_ocsp_response` | Proc | nil | Proc that gets OpenSSL::OCSP::Response. If not needed to staple OCSP::Response, set nil. |
122
123
  | `:compatibility_mode` | Boolean | true | If needed to send ChangeCipherSpec, set true. |
123
124
  | `:loglevel` | Logger constant | Logger::WARN | If needed to print verbose, set Logger::DEBUG. |
124
125
 
@@ -36,7 +36,7 @@ def recv_http_response(client)
36
36
  parser = HTTP::Parser.new
37
37
  buf = nil
38
38
 
39
- parser.on_headers_complete = proc do |headers|
39
+ parser.on_headers_complete = lambda do |headers|
40
40
  buf =
41
41
  [
42
42
  'HTTP/' + parser.http_version.join('.'),
@@ -47,11 +47,11 @@ def recv_http_response(client)
47
47
  + WEBrick::CRLF
48
48
  end
49
49
 
50
- parser.on_body = proc do |chunk|
50
+ parser.on_body = lambda do |chunk|
51
51
  buf += chunk
52
52
  end
53
53
 
54
- parser.on_message_complete = proc do
54
+ parser.on_message_complete = lambda do
55
55
  client.close
56
56
  end
57
57
 
@@ -11,7 +11,7 @@ settings_2nd = {
11
11
  ca_file: File.exist?(ca_file) ? ca_file : nil,
12
12
  alpn: ['http/1.1']
13
13
  }
14
- process_new_session_ticket = proc do |nst, rms, cs|
14
+ process_new_session_ticket = lambda do |nst, rms, cs|
15
15
  return if Time.now.to_i - nst.timestamp > nst.ticket_lifetime
16
16
 
17
17
  settings_2nd[:ticket] = nst.ticket
@@ -11,7 +11,7 @@ settings_2nd = {
11
11
  ca_file: File.exist?(ca_file) ? ca_file : nil,
12
12
  alpn: ['http/1.1']
13
13
  }
14
- process_new_session_ticket = proc do |nst, rms, cs|
14
+ process_new_session_ticket = lambda do |nst, rms, cs|
15
15
  return if Time.now.to_i - nst.timestamp > nst.ticket_lifetime
16
16
 
17
17
  settings_2nd[:key_share_groups] = [] # empty KeyShareClientHello.client_shares
@@ -7,7 +7,7 @@ hostname, port = (ARGV[0] || 'localhost:4433').split(':')
7
7
  ca_file = __dir__ + '/../tmp/ca.crt'
8
8
  req = simple_http_request(hostname)
9
9
 
10
- process_certificate_status = proc do |res, cert, chain|
10
+ process_certificate_status = lambda do |res, cert, chain|
11
11
  puts 'stapled OCSPResponse: '
12
12
  puts res.basic.status.pretty_inspect unless res.nil?
13
13
  puts '-' * 10
@@ -11,7 +11,7 @@ settings_2nd = {
11
11
  ca_file: File.exist?(ca_file) ? ca_file : nil,
12
12
  alpn: ['http/1.1']
13
13
  }
14
- process_new_session_ticket = proc do |nst, rms, cs|
14
+ process_new_session_ticket = lambda do |nst, rms, cs|
15
15
  return if Time.now.to_i - nst.timestamp > nst.ticket_lifetime
16
16
 
17
17
  settings_2nd[:ticket] = nst.ticket
@@ -26,7 +26,7 @@ Etc.nprocessors.times do
26
26
  server = TTTLS13::Server.new(s, settings)
27
27
  parser = HTTP::Parser.new
28
28
 
29
- parser.on_message_complete = proc do
29
+ parser.on_message_complete = lambda do
30
30
  if !parser.http_method.nil?
31
31
  logger.info 'Receive Request'
32
32
  server.write(simple_http_response('TEST'))
@@ -403,23 +403,16 @@ module TTTLS13
403
403
  # @return [Boolean]
404
404
  #
405
405
  # @example
406
- # meth = Client.method(:softfail_check_certificate_status)
406
+ # m = Client.method(:softfail_check_certificate_status)
407
407
  # Client.new(
408
408
  # socket,
409
409
  # hostname,
410
410
  # check_certificate_status: true,
411
- # process_certificate_status: meth
411
+ # process_certificate_status: m
412
412
  # )
413
- # rubocop: disable Metrics/AbcSize
414
- # rubocop: disable Metrics/CyclomaticComplexity
415
- # rubocop: disable Metrics/PerceivedComplexity
416
413
  def self.softfail_check_certificate_status(res, cert, chain)
417
414
  ocsp_response = res
418
- store = OpenSSL::X509::Store.new
419
- store.set_default_paths
420
- context = OpenSSL::X509::StoreContext.new(store, cert, chain)
421
- context.verify
422
- cid = OpenSSL::OCSP::CertificateId.new(cert, context.chain[1])
415
+ cid = OpenSSL::OCSP::CertificateId.new(cert, chain.first)
423
416
 
424
417
  # When NOT received OCSPResponse in TLS handshake, this method will
425
418
  # send OCSPRequest. If ocsp_uri is NOT presented in Certificate, return
@@ -430,23 +423,25 @@ module TTTLS13
430
423
  return true if uri.nil?
431
424
 
432
425
  begin
433
- Timeout.timeout(2) { ocsp_response = send_ocsp_request(cid, uri) }
426
+ # send OCSP::Request
427
+ ocsp_request = gen_ocsp_request(cid)
428
+ Timeout.timeout(2) do
429
+ ocsp_response = send_ocsp_request(ocsp_request, uri)
430
+ end
431
+
432
+ # check nonce of OCSP::Response
433
+ check_nonce = ocsp_request.check_nonce(ocsp_response.basic)
434
+ return true unless [-1, 1].include?(check_nonce)
434
435
  rescue StandardError
435
436
  return true
436
437
  end
437
438
  end
438
- return false \
439
+ return true \
439
440
  if ocsp_response.status != OpenSSL::OCSP::RESPONSE_STATUS_SUCCESSFUL
440
441
 
441
442
  status = ocsp_response.basic.status.find { |s| s.first.cmp(cid) }
442
- return false if status[1] != OpenSSL::OCSP::V_CERTSTATUS_GOOD
443
- return false if !status[3].nil? && status[3] < Time.now
444
-
445
- ocsp_response.basic.verify(chain, store)
443
+ status[1] != OpenSSL::OCSP::V_CERTSTATUS_REVOKED
446
444
  end
447
- # rubocop: enable Metrics/AbcSize
448
- # rubocop: enable Metrics/CyclomaticComplexity
449
- # rubocop: enable Metrics/PerceivedComplexity
450
445
 
451
446
  private
452
447
 
@@ -479,6 +474,9 @@ module TTTLS13
479
474
  rsl = @settings[:record_size_limit]
480
475
  return false if !rsl.nil? && (rsl < 64 || rsl > 2**14 + 1)
481
476
 
477
+ return false if @settings[:check_certificate_status] &&
478
+ @settings[:process_certificate_status].nil?
479
+
482
480
  true
483
481
  end
484
482
  # rubocop: enable Metrics/AbcSize
@@ -530,7 +528,7 @@ module TTTLS13
530
528
  # rubocop: disable Metrics/MethodLength
531
529
  # rubocop: disable Metrics/PerceivedComplexity
532
530
  def gen_ch_extensions
533
- exs = []
531
+ exs = Message::Extensions.new
534
532
  # server_name
535
533
  exs << Message::Extension::ServerName.new(@hostname)
536
534
 
@@ -580,7 +578,7 @@ module TTTLS13
580
578
  exs << Message::Extension::OCSPStatusRequest.new \
581
579
  if @settings[:check_certificate_status]
582
580
 
583
- [Message::Extensions.new(exs), priv_keys]
581
+ [exs, priv_keys]
584
582
  end
585
583
  # rubocop: enable Metrics/AbcSize
586
584
  # rubocop: enable Metrics/CyclomaticComplexity
@@ -673,7 +671,7 @@ module TTTLS13
673
671
  # @return [TTTLS13::Message::Extensions]
674
672
  # @return [Hash of NamedGroup => OpenSSL::PKey::EC.$Object]
675
673
  def gen_newch_extensions(ch1, hrr)
676
- exs = []
674
+ exs = Message::Extensions.new
677
675
  # key_share
678
676
  if hrr.extensions.include?(Message::ExtensionType::KEY_SHARE)
679
677
  group = hrr.extensions[Message::ExtensionType::KEY_SHARE]
@@ -695,7 +693,7 @@ module TTTLS13
695
693
  if hrr.extensions.include?(Message::ExtensionType::COOKIE)
696
694
 
697
695
  # early_data
698
- new_exs = ch1.extensions.merge(Message::Extensions.new(exs))
696
+ new_exs = ch1.extensions.merge(exs)
699
697
  new_exs.delete(Message::ExtensionType::EARLY_DATA)
700
698
 
701
699
  [new_exs, priv_keys]
@@ -541,19 +541,27 @@ module TTTLS13
541
541
 
542
542
  class << self
543
543
  # @param cid [OpenSSL::OCSP::CertificateId]
544
- # @param uri [String]
545
544
  #
546
- # @return [OpenSSL::OCSP::Response]
547
- def send_ocsp_request(cid, uri)
548
- # generate OCSPRequest
545
+ # @return [OpenSSL::OCSP::Request]
546
+ def gen_ocsp_request(cid)
549
547
  ocsp_request = OpenSSL::OCSP::Request.new
550
548
  ocsp_request.add_certid(cid)
551
549
  ocsp_request.add_nonce
550
+ ocsp_request
551
+ end
552
+
553
+ # @param ocsp_request [OpenSSL::OCSP::Request]
554
+ # @param uri_string [String]
555
+ #
556
+ # @raise [Net::OpenTimeout, OpenSSL::OCSP::OCSPError, URI::$Exception]
557
+ #
558
+ # @return [OpenSSL::OCSP::Response, n
559
+ def send_ocsp_request(ocsp_request, uri_string)
552
560
  # send HTTP POST
553
- uri = URI.parse(uri)
561
+ uri = URI.parse(uri_string)
554
562
  path = uri.path
555
563
  path = '/' if path.nil? || path.empty?
556
- http_response = Net::HTTP.start uri.host, uri.port do |http|
564
+ http_response = Net::HTTP.start(uri.host, uri.port) do |http|
557
565
  http.post(
558
566
  path,
559
567
  ocsp_request.to_der,
@@ -1,3 +1,3 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- Dir[File.dirname(__FILE__) + '/cryptograph/*.rb'].each { |f| require f }
3
+ Dir[File.dirname(__FILE__) + '/cryptograph/*.rb'].sort.each { |f| require f }
@@ -78,4 +78,4 @@ module TTTLS13
78
78
  end
79
79
  end
80
80
 
81
- Dir[File.dirname(__FILE__) + '/message/*.rb'].each { |f| require f }
81
+ Dir[File.dirname(__FILE__) + '/message/*.rb'].sort.each { |f| require f }
@@ -8,7 +8,7 @@ module TTTLS13
8
8
  FATAL = "\x02"
9
9
  end
10
10
 
11
- # rubocop: disable Layout/AlignHash
11
+ # rubocop: disable Layout/HashAlignment
12
12
  ALERT_DESCRIPTION = {
13
13
  close_notify: "\x00",
14
14
  unexpected_message: "\x0a",
@@ -38,7 +38,7 @@ module TTTLS13
38
38
  certificate_required: "\x74",
39
39
  no_application_protocol: "\x78"
40
40
  }.freeze
41
- # rubocop: enable Layout/AlignHash
41
+ # rubocop: enable Layout/HashAlignment
42
42
 
43
43
  class Alert
44
44
  attr_reader :level
@@ -44,10 +44,11 @@ module TTTLS13
44
44
  #
45
45
  # @return [TTTLS13::Message::Extensions]
46
46
  # rubocop: disable Metrics/CyclomaticComplexity
47
+ # rubocop: disable Metrics/PerceivedComplexity
47
48
  def self.deserialize(binary, msg_type)
48
49
  raise Error::ErrorAlerts, :internal_error if binary.nil?
49
50
 
50
- extensions = []
51
+ exs = Extensions.new
51
52
  i = 0
52
53
  while i < binary.length
53
54
  raise Error::ErrorAlerts, :decode_error if i + 4 > binary.length
@@ -66,32 +67,41 @@ module TTTLS13
66
67
  ex = Extension::UnknownExtension.new(extension_type: extension_type,
67
68
  extension_data: ex_bin)
68
69
  end
69
- extensions << ex
70
+
71
+ # There MUST NOT be more than one extension of the same type in a
72
+ # given extension block.
73
+ raise Error::ErrorAlerts, :unsupported_extension \
74
+ if exs.include?(extension_type)
75
+
76
+ exs[extension_type] = ex
70
77
  i += ex_len
71
78
  end
72
79
  raise Error::ErrorAlerts, :decode_error unless i == binary.length
73
80
 
74
- Extensions.new(extensions)
81
+ exs
75
82
  end
76
83
  # rubocop: enable Metrics/CyclomaticComplexity
84
+ # rubocop: enable Metrics/PerceivedComplexity
77
85
 
78
86
  # @param key [TTTLS13::Message::ExtensionType]
87
+ # @param default
79
88
  #
80
89
  # @return [TTTLS13::Message::Extension::$Object]
81
- def [](key)
90
+ def fetch(key, default = nil)
82
91
  return nil if super_fetch(key, nil).is_a?(Extension::UnknownExtension)
83
92
 
84
- super_fetch(key, nil)
93
+ super_fetch(key, default)
85
94
  end
86
95
 
87
- # @param key [TTTLS13::Message::ExtensionType]
88
- # @param default
96
+ def [](key)
97
+ fetch(key)
98
+ end
99
+
100
+ # @param ex [TTTLS13::Message::Extension::$Object]
89
101
  #
90
102
  # @return [TTTLS13::Message::Extension::$Object]
91
- def fetch(key, default = nil)
92
- return nil if super_fetch(key, nil).is_a?(Extension::UnknownExtension)
93
-
94
- super_fetch(key, default)
103
+ def <<(ex)
104
+ store(ex.extension_type, ex)
95
105
  end
96
106
 
97
107
  class << self
@@ -111,7 +121,6 @@ module TTTLS13
111
121
  # @return [TTTLS13::Message::Extension::$Object, nil]
112
122
  # rubocop: disable Metrics/CyclomaticComplexity
113
123
  # rubocop: disable Metrics/MethodLength
114
- # rubocop: disable Metrics/PerceivedComplexity
115
124
  def deserialize_extension(binary, extension_type, msg_type)
116
125
  raise Error::ErrorAlerts, :internal_error if binary.nil?
117
126
 
@@ -119,14 +128,15 @@ module TTTLS13
119
128
  when ExtensionType::SERVER_NAME
120
129
  Extension::ServerName.deserialize(binary)
121
130
  when ExtensionType::STATUS_REQUEST
122
- if msg_type == HandshakeType::CLIENT_HELLO # ||
123
- # msg_type == HandshakeType::CERTIFICATE_REQUEST
124
- Extension::OCSPStatusRequest.deserialize(binary)
125
- elsif msg_type == HandshakeType::CERTIFICATE
126
- Extension::OCSPResponse.deserialize(binary)
127
- else
128
- return nil
131
+ if msg_type == HandshakeType::CLIENT_HELLO
132
+ return Extension::OCSPStatusRequest.deserialize(binary)
129
133
  end
134
+
135
+ if msg_type == HandshakeType::CERTIFICATE
136
+ return Extension::OCSPResponse.deserialize(binary)
137
+ end
138
+
139
+ Extension::UnknownExtension.deserialize(binary, extension_type)
130
140
  when ExtensionType::SUPPORTED_GROUPS
131
141
  Extension::SupportedGroups.deserialize(binary)
132
142
  when ExtensionType::SIGNATURE_ALGORITHMS
@@ -155,7 +165,6 @@ module TTTLS13
155
165
  end
156
166
  # rubocop: enable Metrics/CyclomaticComplexity
157
167
  # rubocop: enable Metrics/MethodLength
158
- # rubocop: enable Metrics/PerceivedComplexity
159
168
  end
160
169
  end
161
170
  end
@@ -52,6 +52,7 @@ module TTTLS13
52
52
  signature_algorithms: DEFAULT_SP_SIGNATURE_ALGORITHMS,
53
53
  supported_groups: DEFAULT_SP_NAMED_GROUP_LIST,
54
54
  alpn: nil,
55
+ process_ocsp_response: nil,
55
56
  compatibility_mode: true,
56
57
  loglevel: Logger::WARN
57
58
  }.freeze
@@ -236,10 +237,14 @@ module TTTLS13
236
237
 
237
238
  ch = transcript[CH]
238
239
  rsl = @send_record_size \
239
- unless ch.extensions[Message::ExtensionType::RECORD_SIZE_LIMIT].nil?
240
+ if ch.extensions.include?(Message::ExtensionType::RECORD_SIZE_LIMIT)
240
241
  ee = transcript[EE] = gen_encrypted_extensions(ch, @alpn, rsl)
241
242
  # TODO: [Send CertificateRequest]
242
- ct = transcript[CT] = gen_certificate(@crt, @chain)
243
+
244
+ # status_request
245
+ ocsp_response = fetch_ocsp_response \
246
+ if ch.extensions.include?(Message::ExtensionType::STATUS_REQUEST)
247
+ ct = transcript[CT] = gen_certificate(@crt, @chain, ocsp_response)
243
248
  digest = CipherSuite.digest(@cipher_suite)
244
249
  cv = transcript[CV] = gen_certificate_verify(
245
250
  @key,
@@ -350,7 +355,7 @@ module TTTLS13
350
355
  #
351
356
  # @return [TTTLS13::Message::ServerHello]
352
357
  def send_hello_retry_request(ch1, cipher_suite)
353
- exs = []
358
+ exs = Message::Extensions.new
354
359
  # supported_versions
355
360
  exs << Message::Extension::SupportedVersions.new(
356
361
  msg_type: Message::HandshakeType::SERVER_HELLO
@@ -372,7 +377,7 @@ module TTTLS13
372
377
  random: Message::HRR_RANDOM,
373
378
  legacy_session_id_echo: ch1.legacy_session_id,
374
379
  cipher_suite: cipher_suite,
375
- extensions: Message::Extensions.new(exs)
380
+ extensions: exs
376
381
  )
377
382
  send_handshakes(Message::ContentType::HANDSHAKE, [sh],
378
383
  Cryptograph::Passer.new)
@@ -404,11 +409,16 @@ module TTTLS13
404
409
 
405
410
  # @param crt [OpenSSL::X509::Certificate]
406
411
  # @param chain [Array of OpenSSL::X509::Certificate]
412
+ # @param ocsp_response [OpenSSL::OCSP::Response]
407
413
  #
408
414
  # @return [TTTLS13::Message::Certificate, nil]
409
- def gen_certificate(crt, chain = [])
410
- ces = [crt] + (chain || [])
411
- ces.map! { |c| Message::CertificateEntry.new(c) }
415
+ def gen_certificate(crt, chain = [], ocsp_response = nil)
416
+ exs = Message::Extensions.new
417
+ # status_request
418
+ exs << Message::Extension::OCSPResponse.new(ocsp_response) \
419
+ unless ocsp_response.nil?
420
+ ces = [Message::CertificateEntry.new(crt, exs)] \
421
+ + (chain || []).map { |c| Message::CertificateEntry.new(c) }
412
422
  Message::Certificate.new(certificate_list: ces)
413
423
  end
414
424
 
@@ -444,7 +454,7 @@ module TTTLS13
444
454
  # @return [TTTLS13::Message::Extensions]
445
455
  # @return [OpenSSL::PKey::EC.$Object]
446
456
  def gen_sh_extensions(named_group)
447
- exs = []
457
+ exs = Message::Extensions.new
448
458
  # supported_versions: only TLS 1.3
449
459
  exs << Message::Extension::SupportedVersions.new(
450
460
  msg_type: Message::HandshakeType::SERVER_HELLO
@@ -455,7 +465,7 @@ module TTTLS13
455
465
  = Message::Extension::KeyShare.gen_sh_key_share(named_group)
456
466
  exs << key_share
457
467
 
458
- [Message::Extensions.new(exs), priv_key]
468
+ [exs, priv_key]
459
469
  end
460
470
 
461
471
  # @param ch [TTTLS13::Message::ClientHello]
@@ -464,15 +474,16 @@ module TTTLS13
464
474
  #
465
475
  # @return [TTTLS13::Message::Extensions]
466
476
  def gen_ee_extensions(ch, alpn, record_size_limit)
467
- exs = []
477
+ exs = Message::Extensions.new
468
478
 
469
479
  # server_name
470
480
  exs << Message::Extension::ServerName.new('') \
471
481
  if ch.extensions.include?(Message::ExtensionType::SERVER_NAME)
472
482
 
473
483
  # supported_groups
474
- exs \
475
- << Message::Extension::SupportedGroups.new(@settings[:supported_groups])
484
+ exs << Message::Extension::SupportedGroups.new(
485
+ @settings[:supported_groups]
486
+ )
476
487
 
477
488
  # alpn
478
489
  exs << Message::Extension::Alpn.new([alpn]) unless alpn.nil?
@@ -481,7 +492,7 @@ module TTTLS13
481
492
  exs << Message::Extension::RecordSizeLimit.new(record_size_limit) \
482
493
  unless record_size_limit.nil?
483
494
 
484
- Message::Extensions.new(exs)
495
+ exs
485
496
  end
486
497
 
487
498
  # @param key [OpenSSL::PKey::PKey]
@@ -543,6 +554,11 @@ module TTTLS13
543
554
 
544
555
  matching_san?(crt, server_name)
545
556
  end
557
+
558
+ # @return [OpenSSL::OCSP::Response, nil]
559
+ def fetch_ocsp_response
560
+ @settings[:process_ocsp_response]&.call
561
+ end
546
562
  end
547
563
  # rubocop: enable Metrics/ClassLength
548
564
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TTTLS13
4
- VERSION = '0.2.12'
4
+ VERSION = '0.2.13'
5
5
  end
@@ -2,6 +2,7 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require_relative 'spec_helper'
5
+ using Refinements
5
6
 
6
7
  RSpec.describe Extensions do
7
8
  context 'empty extensions' do
@@ -167,4 +168,19 @@ RSpec.describe Extensions do
167
168
  expect(extensions).to include ExtensionType::RECORD_SIZE_LIMIT
168
169
  end
169
170
  end
171
+
172
+ context 'duplicated extension_type' do
173
+ let(:server_name) do
174
+ ServerName.new('example.com')
175
+ end
176
+
177
+ let(:testbinary) do
178
+ server_name.serialize * 2
179
+ end
180
+
181
+ it 'should raise error, if extension_type get duplicated' do
182
+ expect { Extensions.deserialize(testbinary, HandshakeType::CLIENT_HELLO) }
183
+ .to raise_error(ErrorAlerts)
184
+ end
185
+ end
170
186
  end
@@ -187,7 +187,7 @@ RSpec.describe ServerHello do
187
187
  let(:message) do
188
188
  sh = ServerHello.deserialize(TESTBINARY_SERVER_HELLO)
189
189
  extensions = sh.instance_variable_get(:@extensions)
190
- extensions[ExtensionType::SUPPORTED_VERSIONS] = nil
190
+ extensions.delete(ExtensionType::SUPPORTED_VERSIONS)
191
191
  sh.instance_variable_set(:@extensions, extensions)
192
192
  sh
193
193
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tttls1.3
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.12
4
+ version: 0.2.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - thekuwayama
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-01-04 00:00:00.000000000 Z
11
+ date: 2020-01-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler