Module: EchSpec::Spec

Defined in:
lib/echspec/spec.rb,
lib/echspec/spec.rb,
lib/echspec/spec/9.rb,
lib/echspec/spec/7-5.rb,
lib/echspec/spec/5.1-9.rb,
lib/echspec/spec/5.1-10.rb,
lib/echspec/spec/7.1-11.rb,
lib/echspec/spec/7.1.1-2.rb,
lib/echspec/spec/7.1.1-5.rb,
lib/echspec/spec/7.1-14.2.1.rb

Defined Under Namespace

Classes: ResultDescURL, Spec5_1_10, Spec5_1_9, Spec7_1_11, Spec7_1_14_2_1, Spec7_1_1_2, Spec7_1_1_5, Spec7_5, Spec9, WithSocket

Class Method Summary collapse

Class Method Details

.desc(description, section) ⇒ String

Parameters:

  • description (String)
  • section (String)

Returns:

  • (String)


143
144
145
# File 'lib/echspec/spec.rb', line 143

def desc(description, section)
  "#{description} [#{section}]"
end

.do_run(port, hostname, ech_config, targets, verbose) ⇒ Object

Parameters:

  • port (Integer)
  • hostname (String)
  • ech_config (ECHConfig)
  • targets (Array<EchSpec::SpecGroup>)
  • verbose (Boolean)


126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/echspec/spec.rb', line 126

def do_run(port, hostname, ech_config, targets, verbose)
  rdus = targets.flat_map do |g|
    g.spec_cases.map do |sc|
      result = sc.method.call(hostname, port, ech_config)
      desc = desc(sc.description, g.section)
      url = url(g.section)
      ResultDescURL.new(result:, desc:, url:)
    end
  end

  print_results(rdus, verbose)
end

.expect_alert(msg, desc) ⇒ Boolean

Parameters:

  • msg (TTTLS13::Message::Record)
  • desc (Symbol)

Returns:

  • (Boolean)


10
11
12
13
# File 'lib/echspec/spec.rb', line 10

def expect_alert(msg, desc)
  msg.is_a?(TTTLS13::Message::Alert) &&
    msg.description == TTTLS13::Message::ALERT_DESCRIPTION[desc]
end

Parameters:

  • err (EchSpec::Err)
  • url (String)
  • idx (Integer)
  • desc (String)
  • verbose (Boolean)


51
52
53
54
55
56
57
# File 'lib/echspec/spec.rb', line 51

def print_err_details(err, url, idx, desc, verbose)
  puts "#{idx + 1}) #{desc}".indent
  puts url.indent.indent
  puts err.details.indent.indent
  warn err.message_stack if verbose && !err.message_stack.nil?
  puts
end

Parameters:

  • rds (Array<ResultDescURL>)

    result: EchSpec::Ok | Err, desc: String

  • verbose (Boolean)


19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/echspec/spec.rb', line 19

def print_results(rdus, verbose)
  rdus.each { |rdu| print_summary(rdu.result, rdu.desc) }
  failures = rdus.filter { |rdu| rdu.result.is_a? Err }
  return if failures.empty?

  puts
  puts 'Failures:'
  puts
  failures.each
          .with_index { |rdu, idx| print_err_details(rdu.result, rdu.url, idx, rdu.desc, verbose) }
  puts "#{failures.length} failure".red
end

Parameters:



34
35
36
37
38
39
40
41
42
43
44
# File 'lib/echspec/spec.rb', line 34

def print_summary(result, desc)
  check = "\u2714"
  cross = "\u0078"
  summary = case result
            in Ok
              "#{check} #{desc}".green.indent
            in Err
              "#{cross} #{desc}".red.indent
            end
  puts summary
end

.run(fpath, port, hostname, force_compliant, verbose) ⇒ Object

Parameters:

  • fpath (String | NilClass)
  • port (Integer)
  • hostname (String)
  • force_compliant (Boolean)
  • verbose (Boolean)


97
98
99
100
101
102
103
# File 'lib/echspec/spec.rb', line 97

def run(fpath, port, hostname, force_compliant, verbose)
  TTTLS13::Logging.logger.level = Logger::WARN
  puts 'TLS Encrypted Client Hello Server'
  ech_config = try_get_ech_config(fpath, hostname, force_compliant)

  do_run(port, hostname, ech_config, spec_groups, verbose)
end

.run_only(fpath, port, hostname, sections, verbose) ⇒ Object

Parameters:

  • fpath (String | NilClass)
  • port (Integer)
  • hostname (String)
  • sections (Array<String>)
  • verbose (Boolean)


110
111
112
113
114
115
116
117
118
119
# File 'lib/echspec/spec.rb', line 110

def run_only(fpath, port, hostname, sections, verbose)
  targets = spec_groups.filter { |g| sections.include?(g.section) }
  force_compliant = sections.include?(Spec9.section)

  TTTLS13::Logging.logger.level = Logger::WARN
  puts 'TLS Encrypted Client Hello Server'
  ech_config = try_get_ech_config(fpath, hostname, force_compliant)

  do_run(port, hostname, ech_config, targets, verbose)
end

.sectionsObject



187
188
189
# File 'lib/echspec/spec.rb', line 187

def sections
  (spec_groups + [Spec9]).map(&:section)
end

.spec_groupsObject



177
178
179
180
181
182
183
184
185
# File 'lib/echspec/spec.rb', line 177

def spec_groups
  # https://datatracker.ietf.org/doc/html/draft-ietf-tls-esni-22#section-5
  groups = [Spec5_1_9, Spec5_1_10]

  # https://datatracker.ietf.org/doc/html/draft-ietf-tls-esni-22#section-7
  groups += [Spec7_5, Spec7_1_11, Spec7_1_14_2_1, Spec7_1_1_2, Spec7_1_1_5]

  groups.map(&:spec_group)
end

.try_get_ech_config(fpath, hostname, force_compliant) ⇒ ECHConfig

Parameters:

  • fpath (String | NilClass)
  • hostname (String)
  • force_compliant (Boolean)

Returns:

  • (ECHConfig)


159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/echspec/spec.rb', line 159

def try_get_ech_config(fpath, hostname, force_compliant)
  # https://datatracker.ietf.org/doc/html/draft-ietf-tls-esni-22#section-9
  result = Spec9.try_get_ech_config(fpath, hostname, force_compliant)
  desc = desc(Spec9.description, Spec9.section)
  url = url(Spec9.section)

  case result
  in Ok(ech_config) if force_compliant
    print_summary(result, desc)
    ech_config
  in Ok(ech_config)
    ech_config
  in Err(details, _)
    print_results([ResultDescURL.new(result:, desc:, url:)], true)
    exit 1
  end
end

.url(section) ⇒ String

Parameters:

  • section (String)

Returns:

  • (String)


150
151
152
# File 'lib/echspec/spec.rb', line 150

def url(section)
  "https://datatracker.ietf.org/doc/html/draft-ietf-tls-esni-22#section-#{section}"
end